package com.wlsk.license.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageInfo;
import com.wlsk.license.cache.UserSessionManager;
import com.wlsk.license.common.constant.CharteredLicenseConstant;
import com.wlsk.license.common.constant.RedisService;
import com.wlsk.license.common.enums.*;
import com.wlsk.license.common.exception.BusinessException;
import com.wlsk.license.common.result.Result;
import com.wlsk.license.common.utils.ByteArrayMultipartFile;
import com.wlsk.license.common.utils.ConvertUtil;
import com.wlsk.license.common.utils.OrderLockUtils;
import com.wlsk.license.dao.entity.*;
import com.wlsk.license.dao.mapper.*;
import com.wlsk.license.dto.*;
import com.wlsk.license.dto.request.*;
import com.wlsk.license.dto.request.feign.MerchantReqDto;
import com.wlsk.license.dto.response.*;
import com.wlsk.license.dto.response.feign.OssObjectInfoResultDto;
import com.wlsk.license.dto.response.feign.UserResDto;
import com.wlsk.license.dto.zz.GenerateCharterPlateReturnDto;
import com.wlsk.license.dto.zz.LicenseInfoDto;
import com.wlsk.license.dto.zz.UpLoadReturnDto;
import com.wlsk.license.service.*;
import com.wlsk.license.service.export.PlateExportService;
import com.wlsk.license.service.feign.MerchantFeignClient;
import com.wlsk.license.service.zpff.CharterApplyLicense;
import com.wlsk.license.service.zpff.RtabTokenHelper;
import com.zhongjinfeng.util.base.ObjectHelper;
import com.zhongjinfeng.util.helper.DateHelper;
import com.zhongjinfeng.util.helper.JsonHelper;
import com.zhongjinfeng.util.helper.StringHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.github.pagehelper.page.PageMethod.startPage;

/**
 * <p>
 * 包车牌业户信息 服务实现类
 * </p>
 *
 * @author liuzhangbin
 * @since 2025-08-26
 */
@Service
@Slf4j
public class PlateManageServiceImpl extends BaseService implements IPlateManageService {
    public static final String INTER_PROVINCIAL = "20000947"; // 省际包车牌
    // 运管签发账户
    public static final String SIGN_ACCOUNT_TYPE = "301-09";
    @Autowired
    private PlateDriverMapper plateDriverMapper;//包车牌驾驶员信息表

    @Autowired
    private PlateOwnerMapper plateOwnerMapper;//包车牌业户信息表

    @Autowired
    private PlateMapper plateMapper;//包车牌表

    @Autowired
    private PlateLineMapper plateLineMapper;//包车牌运次信息表

    @Autowired
    private PlateOperateLogMapper plateOperateLogMapper;//包车牌操作日志表

    @Autowired
    private PlateVehicleMapper plateVehicleMapper;//包车牌车辆信息

    @Autowired
    private PlateSignMapper plateSignMapper;//包车牌签发记录

    @Autowired
    private PlateAnnexMapper plateAnnexMapper;//包车牌附件记录表

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private MerchantFeignClient merchantFeignClient;//商户服务

    @Autowired
    IFileUploadService fileUploadService;

    @Autowired
    ISysRegionService sysRegionService;//获取行政区划

    @Autowired
    IReprintTaskService reprintTaskService;

    @Autowired
    PlateExportService plateExportService;

    @Resource
    private RedisService redisService;

    @Autowired
    IExportRecordService exportRecordService;//导出日志记录

    @Autowired
    private ISysDictService sysDictService;

    public Result<GetPlateOwnerReturnDto> getOwnerInfo2(GetOwnerInfoReqDto reqDto) {
        PlateOwner existPlateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        if (existPlateOwner != null) {
            PlateOwnerDto plateOwnerInfo = new PlateOwnerDto();
            ObjectHelper.writeWithFrom(plateOwnerInfo, existPlateOwner);
            GetPlateOwnerReturnDto res = new GetPlateOwnerReturnDto();
            res.setPlateId(reqDto.getPlateId());
            res.setPlateOnwerInfo(plateOwnerInfo);
            return Result.success(res);
        } else {
            return Result.failed("获取失败");
        }
    }

    @Override
    public Result<GetPlateOwnerReturnDto> getOwnerInfo(PlateOwnerReqDto reqDto) {
//        reqDto.setLiceno("500102900142");
        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(reqDto), CharterApplyLicense.GET_OWNER_INFO);
        if ("200".endsWith(map.get("code"))) {
            PlateOwnerDto plateOwnerDto = JSON.parseObject(JSON.toJSONString(getValue(map.get("data"))), PlateOwnerDto.class);
            GetPlateOwnerReturnDto res = new GetPlateOwnerReturnDto();
            res.setPlateId(reqDto.getPlateId());
            res.setPlateOnwerInfo(plateOwnerDto);
            return Result.success(res);
        } else {
            return Result.failed(map.get("data"));
        }
    }


    /**
     * 1、根据经营许可证获取业户信息（http://113.207.113.130:28080/ZPFF_API/outInterface/getOwnerInfo.interface）
     * 接口返回解析
     * 获取本系统文档内的字段
     */

    private JSONObject getValue(String str) {
        JSONObject obj = JSONObject.parseObject(str);
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("operateRange", obj.get("scopenames"));
        jsonParam.put("ownerId", obj.get("ownerid"));
        jsonParam.put("ownerName", obj.get("ownername"));
        jsonParam.put("liceno", obj.get("liceno"));
        jsonParam.put("cardBeginDate", obj.get("cardbegindate"));
        jsonParam.put("cardEndDate", obj.get("cardenddate"));
        jsonParam.put("address", obj.get("address"));
        jsonParam.put("economicType", obj.get("economictype"));
        jsonParam.put("examrank", obj.get("examRank"));
        jsonParam.put("kyNum", obj.get("kyNum"));
        jsonParam.put("kyzwNum", obj.get("kyzwNum"));
        jsonParam.put("gjNum", obj.get("gjNum"));
        jsonParam.put("gjzwNum", obj.get("gjzwNum"));
        jsonParam.put("zjNum", obj.get("zjNum"));
        jsonParam.put("zjzwNum", obj.get("zjzwNum"));
        jsonParam.put("chargerName", obj.get("chargername"));
        jsonParam.put("contactTel", obj.get("contacttel"));
        jsonParam.put("manunitCode", obj.get("manunitcode"));
        return jsonParam;
    }

    /**
     * 2、下一步，反馈业户信息（http://113.207.113.130:28080/ZPFF_API/outOwnerInterface/rebackOwnerInfo.interface）
     * 接口入参
     * 构造用户信息
     */
    public Map<String, Object> postOwnerOfPropertyMap(PlateOwnerPostReqDto reqDto, Plate plate) {
        Map<String, Object> paramMap = new HashMap<>();
        // 数据来源 1 渝客行
        paramMap.put("dataSource", "1");
        paramMap.put("appid", "");
        paramMap.put("appnumber", "");
        if (plate != null && !StringHelper.isEmpty(plate.getTradeAppId())) {
            paramMap.put("appid", plate.getTradeAppId() != null ? plate.getTradeAppId() : "");
        }
        if (plate != null && !StringHelper.isEmpty(plate.getTradeAppNumber())) {
            paramMap.put("appnumber", plate.getTradeAppNumber() != null ? plate.getTradeAppNumber() : "");
        }
        PlateOwnerDto bo = reqDto.getPlateOwnerInfo();
        // 业户ID
        paramMap.put("cyhid", bo.getOwnerId() != null ? bo.getOwnerId() : "");
        // 经营许可证号
        paramMap.put("licenseno", bo.getLiceno() != null && !bo.getLiceno().equals("") ? bo.getLiceno() : "");
        // 业户名称
        paramMap.put("ownername", bo.getOwnerName() != null && !bo.getOwnerName().equals("") ? bo.getOwnerName() : "");
        // 业户地址
        paramMap.put("baseaddress", bo.getAddress() != null && !bo.getAddress().equals("") ? bo.getAddress() : "");
        // 经营范围
        paramMap.put("houseproducts", bo.getOperateRange() != null && !bo.getOperateRange().equals("") ? bo.getOperateRange() : "");
        //
        paramMap.put("representative", "");
        paramMap.put("corpContacts", "");
        // 联系人
        paramMap.put("contactperson", bo.getChargerName() != null && !bo.getChargerName().equals("") ? bo.getChargerName() : "");
        // 联系人电话
        paramMap.put("telephone", bo.getContactTel() != null && !bo.getContactTel().equals("") ? bo.getContactTel() : "");
        // Date date = new Date();
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 申请日期YYYY-MM-DD hh:mm:ss
        paramMap.put("appDate", sd.format(new Date()));
        paramMap.put("state", "");
        // 包车业户所属机构
        paramMap.put("unitno", bo.getManunitCode() != null && !bo.getManunitCode().equals("") ? bo.getManunitCode() : "");
        paramMap.put("locking", "");
        // 许可证有效开始日期YYYY-MM-DD hh:mm:ss
        paramMap.put("qcqssj", bo.getCardBeginDate() != null ? bo.getCardBeginDate() : "");
        // paramMap.put("qcqssj", date);
        // 许可证有效结束日期
        paramMap.put("yhjsrq", bo.getCardEndDate() != null ? bo.getCardEndDate() : "");
        // paramMap.put("yhjsrq", date);
        // 经济类型
        paramMap.put("cjjlx", bo.getEconomicType() != null && !bo.getEconomicType().equals("") ? bo.getEconomicType() : "");
        paramMap.put("cyb", "");
        // 客运车辆数量
        paramMap.put("kyclnum", bo.getKyNum() != null ? bo.getKyNum() : "");
        // 客运车辆总座位数
        paramMap.put("kyclnumzws", bo.getKyzwNum() != null ? bo.getKyzwNum() : "");
        // 高级车数量
        paramMap.put("gjcs", bo.getGjNum() != null ? bo.getGjNum() : "");
        // 高级车总座位数
        paramMap.put("gjczws", bo.getGjzwNum() != null ? bo.getGjzwNum() : "");
        // 中级车数量
        paramMap.put("zjcs", bo.getZjNum() != null ? bo.getZjNum() : "");
        // 中级车总座位数
        paramMap.put("zjczws", bo.getZjzwNum() != null ? bo.getZjzwNum() : "");
        paramMap.put("qyqfr", "");
        paramMap.put("remarks", "");
        // 安全服务年度考核
        paramMap.put("ckhdj", bo.getExamrank() != null && !bo.getExamrank().equals("") ? bo.getExamrank() : "");
        paramMap.put("fjAddressCode", "");
        paramMap.put("auditCounties", "");
        paramMap.put("bcpSq2Pageurl", "");
        paramMap.put("statuName", "");
        paramMap.put("noInStatu", "");
        paramMap.put("haveInStatu", "");
        paramMap.put("taskID", "");
        paramMap.put("isfirstCheck", "");
        // 查询条件——开始时间 (传当前时间)
        paramMap.put("appdateBeginQuery", sd.format(new Date()));
        // 查询条件——结束时间(传当前时间)
        paramMap.put("appdateEndQuery", sd.format(new Date()));
        paramMap.put("companyQuery", "");
        paramMap.put("PageState", "");
        paramMap.put("licenseplateQuery", "");
        paramMap.put("licensePlatePage", "");
        paramMap.put("departureaddressPage", "");
        paramMap.put("theendaddressPage", "");
        paramMap.put("totalmileagePage", "");
        // 使用期限起(传当前时间)
        paramMap.put("limitstartPage", sd.format(new Date()));
        paramMap.put("limitendPage", sd.format(new Date()));
        paramMap.put("operator", "");
        paramMap.put("cjjlxName", "");
        paramMap.put("auditcountiesName", "");
        paramMap.put("organizationcode", "");
        paramMap.put("operatorcode", "");
        return paramMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<PlateOwnerPostResultDto> postOwnerInfo(PlateOwnerPostReqDto reqDto) {
        // TODO: 2025/9/25 如果没有包车牌id则表示响应表还未创建，第一次点击
        // 2. 查询是否存在：根据 userCode 查记录（只查 id 和必要字段）
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        //正常返回后需要创建相关表
        Result<UserResDto> result = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!result.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        // 存在：设置主键，执行更新
        Map<String, Object> stringObjectMap = postOwnerOfPropertyMap(reqDto, plate);
        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(stringObjectMap), CharterApplyLicense.REBACK_OWNER_INFO);
        if ("200".endsWith(map.get("code"))) {
            JSONObject obj = JSONObject.parseObject(map.get("data"));
            //1、创建包车牌信息表
            if (plate == null) {
                //防止编号重复
                plate = new Plate();
                if (obj.get("appid") != null) {
                    plate.setTradeAppId(obj.getInteger("appid"));
                }
                plate.setTradeAppNumber(obj.getString("appnumber"));
                plate.setCreateTime(LocalDateTime.now());
                //申请人id
                plate.setCreateId(reqDto.getUid());
                //申请时间
                plate.setApplyTime(LocalDateTime.now());
                //当前状态草稿
                plate.setCharterPlateStatus(CharterPlateStatusEnum.DRAFT.getCode());
                String applyNumber = "";
                if (result != null && result.getData() != null && result.getData().getOrgVo() != null) {
                    plate.setCreateBy(result.getData().getNickname());
                    plate.setOrgId(result.getData().getOrgVo().getOrgId());
                    plate.setOrgName(result.getData().getOrgVo().getOrgName());
                    plate.setDeptId(result.getData().getDeptId());
                    //根据商户id查询当天最大订单号
                    int nextSeq = plateMapper.selectNextSequence(result.getData().getOrgVo().getMerchantCode());
                    // 3. 校验是否超限
                    if (nextSeq > 9999) {
                        return Result.failed("当日申请编号已达上限（9999）");
                    }
                    // 1. 获取当前日期（注意时区）
                    String dateStr = LocalDate.now(ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ofPattern("yyMMdd"));
                    applyNumber = result.getData().getOrgVo().getMerchantCode() + dateStr + String.format("%04d", nextSeq);
                    //申请编号
                    plate.setApplyNumber(applyNumber);
                }
                plateMapper.insert(plate);
                //2.写业户信息表

                //操作日志记录保存
                super.addOperateLog(plate.getId(), reqDto.getUid(), OperateLogTempEnum.CREATE_DRAFT, false);
            } else {
                //更新
                if (obj.get("appid") != null) {
                    plate.setTradeAppId(obj.getInteger("appid"));
                }
                plate.setTradeAppNumber(obj.getString("appnumber"));
                plate.setUpdateTime(LocalDateTime.now());
                plate.setUpdateId(reqDto.getUid());
                plate.setUpdateBy(result.getData().getNickname());
                plateMapper.updateById(plate);
            }
            //2、创建业户信息表
            // 2. 查询是否存在：根据 userCode 查记录（只查 id 和必要字段）
            PlateOwner existPlateOwner = plateOwnerMapper.selectById(plate.getId());
            // 3. 判断是否存在
            if (existPlateOwner != null && existPlateOwner.getId() != null) {
                BeanUtils.copyProperties(reqDto.getPlateOwnerInfo(), existPlateOwner);
                existPlateOwner.setUpdateTime(LocalDateTime.now());
                existPlateOwner.setUpdateId(reqDto.getUid());
                existPlateOwner.setUpdateBy(result.getData().getNickname());
                plateOwnerMapper.updateById(existPlateOwner);
            } else {
                existPlateOwner = new PlateOwner();
                BeanUtils.copyProperties(reqDto.getPlateOwnerInfo(), existPlateOwner);
                // 不存在：插入新记录
                existPlateOwner.setId(plate.getId());
                existPlateOwner.setCreateTime(LocalDateTime.now());
                existPlateOwner.setCreateId(reqDto.getUid());
                existPlateOwner.setCreateBy(result.getData().getNickname());
                plateOwnerMapper.insert(existPlateOwner);
            }
            // 返回结果 并给出plateId 供后续流程使用
            PlateOwnerPostResultDto resultDto = JSON.parseObject(map.get("data"), PlateOwnerPostResultDto.class);
            resultDto.setPlateId(plate.getId());
            return Result.success(resultDto);
        } else {
            return Result.failed(map.get("msg"));
        }
    }

    @Override
    public Result<?> getCitiesDj(CityCodeReqDto reqDto) {
        // 4个直辖市北京-110000、天津-120000、重庆-500000、上海-310000
        //获取省 00550001
//        List<SysRegion> sysRegions = sysRegionService.getBaseMapper().selectList(new LambdaQueryWrapper<SysRegion>().eq(SysRegion::getCLevel, "00550001"));
        // 获取所有行政区划数据
        List<SysRegion> allRegions = sysRegionService.list();
        // 按层级分组
        Map<String, SysRegion> provinceMap = new HashMap<>();
        Map<String, SysRegion> cityMap = new HashMap<>();
        Map<String, SysRegion> areaMap = new HashMap<>();
        // 根据编码长度区分省市区
        for (SysRegion region : allRegions) {
            //省 市 区
            String code = region.getCLevel();
            String id = region.getCXzqhId();
            if (!StringHelper.isEmpty(code) && !StringHelper.isEmpty(id)) {
                if ("00550001".equals(code)) {
                    provinceMap.put(id, region);
                } else if ("00550002".equals(code)) {
                    cityMap.put(id, region);
                } else if ("00550003".equals(code)) {
                    areaMap.put(id, region);
                }
            }
        }
        // 构建省市区三级嵌套结构
        List<ProvinceDto> provinces = new ArrayList<>();
        for (Map.Entry<String, SysRegion> provinceEntry : provinceMap.entrySet()) {
            //行政区划id
            String provinceCode = provinceEntry.getKey();
            ProvinceDto provinceDto = new ProvinceDto();
            provinceDto.setCode(provinceCode);
            provinceDto.setName(provinceEntry.getValue().getCName());
            provinceDto.setCities(new ArrayList<>());
            // 查找该省下的所有市
            if (provinceCode.equals("10000001") || provinceCode.equals("10000002") || provinceCode.equals("10000009") || provinceCode.equals("10000022")) {
                provinceDto.setType("municipality");
                // 查找该市下的所有区县
                for (Map.Entry<String, SysRegion> areaEntry : areaMap.entrySet()) {
                    String areaCode = areaEntry.getKey();
                    SysRegion areaRegion = areaEntry.getValue();
                    if (areaRegion.getCParentSj().equals(provinceCode)) {
                        CityDto cityDto = new CityDto();
                        cityDto.setCode(areaCode);
                        cityDto.setName(areaRegion.getCName());
                        cityDto.setCities(new ArrayList<>());
                        provinceDto.getCities().add(cityDto);
                    }
                }
            } else {
                provinceDto.setType("province");
                for (Map.Entry<String, SysRegion> cityEntry : cityMap.entrySet()) {
                    String cityCode = cityEntry.getKey();
                    SysRegion cityRegion = cityEntry.getValue();
                    // 判断是否属于当前省（前两位相同）
                    if (cityRegion.getCParentSj().equals(provinceCode)) {
                        CityDto cityDto = new CityDto();
                        cityDto.setCode(cityCode);
                        cityDto.setName(cityRegion.getCName());
                        cityDto.setCities(new ArrayList<>());
                        // 查找该市下的所有区县
                        for (Map.Entry<String, SysRegion> areaEntry : areaMap.entrySet()) {
                            String areaCode = areaEntry.getKey();
                            SysRegion areaRegion = areaEntry.getValue();
                            if (areaRegion.getCParentDj().equals(cityCode)) {
                                AreaDto areaDto = new AreaDto();
                                areaDto.setCode(areaCode);
                                areaDto.setName(areaRegion.getCName());
                                cityDto.getCities().add(areaDto);
                            }
                        }
                        provinceDto.getCities().add(cityDto);
                    }
                }
            }
            provinces.add(provinceDto);
        }
        return Result.success(provinces);
    }

    /**
     * 反馈运次信息提交
     *
     * @param postPlateLineReqDto
     * @return
     */
    @Override
    public Result<?> postTransportatinCycle(PostPlateLineReqDto postPlateLineReqDto) {
        boolean flag;
        // TODO: 2025/9/25 先保存运次信息
        PlateLine existPlateLine = plateLineMapper.selectById(postPlateLineReqDto.getPlateId());
        Plate plate = plateMapper.selectById(postPlateLineReqDto.getPlateId());
        if (plate != null && plate.getTradeAppId() != null) {

        } else {
            return Result.failed("包车牌信息不存在");
        }
        // 3. 判断是否存在
        if (existPlateLine != null && existPlateLine.getId() != null) {
            postPlateLineReqDto.getPlateLineInfo().setLineId(existPlateLine.getLineId());
        }
        Result<UserResDto> result = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(postPlateLineReqDto.getUid()).build());
        if (!result.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setTransportatinCycleValue(postPlateLineReqDto, plate)), CharterApplyLicense.REBACK_YCINFO);
        if (!"200".endsWith(map.get("code"))) {
            return Result.failed(map.get("data"));
        }
        PlateLineDto reqDto = postPlateLineReqDto.getPlateLineInfo();
        // 3. 判断是否存在
        if (existPlateLine != null && existPlateLine.getId() != null) {
            ObjectHelper.writeWithFrom(existPlateLine, reqDto);
            existPlateLine.setLineId(JSONObject.parseObject(map.get("data")).getInteger("lineid"));
            existPlateLine.setUpdateTime(LocalDateTime.now());
            //需要将起始地 、目的地、终审地 解析存入线路表
            if (reqDto.getDeparture() != null && reqDto.getDeparture().split("-").length > 2) {
                existPlateLine.setStartProvince(reqDto.getDeparture().split("-")[0]);
                existPlateLine.setStartCity(reqDto.getDeparture().split("-")[1]);
                existPlateLine.setStartCounty(reqDto.getDeparture().split("-")[2]);
            }

            if (reqDto.getTheend() != null && reqDto.getTheend().split("-").length > 2) {
                existPlateLine.setEndProvince(reqDto.getTheend().split("-")[0]);
                existPlateLine.setEndCity(reqDto.getTheend().split("-")[1]);
                existPlateLine.setEndCounty(reqDto.getTheend().split("-")[2]);
            }

            if (reqDto.getAuditCounties() != null && reqDto.getAuditCounties().split("-").length > 2) {
                existPlateLine.setAuditProvince(reqDto.getTheend().split("-")[0]);
                existPlateLine.setAuditCity(reqDto.getTheend().split("-")[1]);
                existPlateLine.setAuditCounty(reqDto.getTheend().split("-")[2]);
            }

            existPlateLine.setUpdateId(reqDto.getUid());
            existPlateLine.setUpdateTime(LocalDateTime.now());
            if (result != null && result.getData() != null) {
                existPlateLine.setUpdateBy(result.getData().getNickname());
            }
            plateLineMapper.updateById(existPlateLine);
        } else {
            existPlateLine = new PlateLine();
            ObjectHelper.writeWithFrom(existPlateLine, reqDto);
            existPlateLine.setId(postPlateLineReqDto.getPlateId());
            existPlateLine.setLineId(JSONObject.parseObject(map.get("data")).getInteger("lineid"));
            //需要将起始地 、目的地、终审地 解析存入线路表
            if (reqDto.getDeparture() != null && reqDto.getDeparture().split("-").length > 2) {
                existPlateLine.setStartProvince(reqDto.getDeparture().split("-")[0]);
                existPlateLine.setStartCity(reqDto.getDeparture().split("-")[1]);
                existPlateLine.setStartCounty(reqDto.getDeparture().split("-")[2]);
            }

            if (reqDto.getTheend() != null && reqDto.getTheend().split("-").length > 2) {
                existPlateLine.setEndProvince(reqDto.getTheend().split("-")[0]);
                existPlateLine.setEndCity(reqDto.getTheend().split("-")[1]);
                existPlateLine.setEndCounty(reqDto.getTheend().split("-")[2]);
            }

            if (reqDto.getAuditCounties() != null && reqDto.getAuditCounties().split("-").length > 2) {
                existPlateLine.setAuditProvince(reqDto.getTheend().split("-")[0]);
                existPlateLine.setAuditCity(reqDto.getTheend().split("-")[1]);
                existPlateLine.setAuditCounty(reqDto.getTheend().split("-")[2]);
            }

            // 不存在：插入新记录
            existPlateLine.setCreateId(reqDto.getUid());
            existPlateLine.setCreateTime(LocalDateTime.now());
            if (result != null && result.getData() != null && result.getData().getOrgVo() != null) {
                existPlateLine.setCreateBy(result.getData().getNickname());
            }
            plateLineMapper.insert(existPlateLine);
        }

        // 更新Plate表的运次相关信息

        // TODO: 2025年10月9日 包车类型和包车牌类型重复
        //包车牌类型
        plate.setCharterPlateType(reqDto.getCardType());
        //包车类型
        plate.setCharterType(reqDto.getLicplaType());
        //线路起点区域, 所属行政区划  起始地省、市、区县编码用“-”连起来
        plate.setRouteStartPlace(reqDto.getDeparture());
        //线路终点区域, 所属行政区划  起始地省、市、区县编码用“-”连起来
        plate.setRouteEndPlace(reqDto.getTheend());
        //省际包车牌 为纸质包车牌
        if (INTER_PROVINCIAL.equals(existPlateLine.getCardType())) {
            plate.setPlateProduceType(CharterPlateProductTypeEnum.PAPER_CHARTER_PLATE.getCode());
        } else {
            //电子包车牌
            plate.setPlateProduceType(CharterPlateProductTypeEnum.ELECTRONIC_CHARTER_PLATE.getCode());
        }
        if (reqDto.getLimitStart() != null) {
            plate.setBeginDate(reqDto.getLimitStart());
        }
        if (reqDto.getLimitEnd() != null) {
            plate.setEndDate(reqDto.getLimitEnd());
        }
        plate.setUpdateTime(LocalDateTime.now());
        plateMapper.updateById(plate);

        Map map2 = new HashMap();
        map2.put("plateId", postPlateLineReqDto.getPlateId());
        return Result.success(map2);
    }

    /**
     * 获取车辆信息
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<CarInfoReturnDto> getCarInfo(CarInfoReqDto reqDto) {
        Map<String, Object> stringObjectMap = new HashMap<>();
        stringObjectMap.put("licenseplate", reqDto.getLicenseplate());
        // TODO: 2025/9/25通过plateID 获取
        PlateOwner existPlateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        if (existPlateOwner != null) {
            stringObjectMap.put("licenseno_yh", existPlateOwner.getLiceno());
            Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(stringObjectMap), CharterApplyLicense.GET_VEHCILEINFO_URL);
            if ("200".endsWith(map.get("code"))) {

                GetCarInfoReturnDto getCarInfoReturnDto = JsonHelper.deserialize(map.get("data"), GetCarInfoReturnDto.class);
                CarInfoDto carInfoDto = new CarInfoDto();
                GetCarInfoDto getCarInfoDto = getCarInfoReturnDto.getVehicleQueryList().get(0);
                ObjectHelper.writeWithFrom(carInfoDto, getCarInfoDto);
                ObjectHelper.writeWithFrom(carInfoDto, getCarInfoReturnDto);
                carInfoDto.setLicensenoYh(getCarInfoDto.getLicenseno_yh());
                carInfoDto.setLimitEndXl(getCarInfoDto.getLimitend_xl());
                carInfoDto.setLimitStartXl(getCarInfoDto.getLimitstart_xl());
                carInfoDto.setTotalMileageXl(getCarInfoDto.getTotalMileageXl());

                CarInfoReturnDto res = new CarInfoReturnDto();
                res.setCarInfo(carInfoDto);
                res.setPlateId(reqDto.getPlateId());
                return Result.success(res);
            } else {
                return Result.failed(map.get("data"));
            }
        } else {
            return Result.failed("获取车辆信息失败！请联系管理员");
        }
    }


    /**
     * 获取车辆信息
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<CarInfoReturnDto> getCarInfo2(CarInfoReq2Dto reqDto) {
        // TODO: 2025/9/25通过plateID 获取
        PlateVehicle plateVehicle = plateVehicleMapper.selectById(reqDto.getPlateId());
        if (plateVehicle != null) {
            CarInfoDto res = new CarInfoDto();
            ObjectHelper.writeWithFrom(res, plateVehicle);

            CarInfoReturnDto returnDto = new CarInfoReturnDto();
            returnDto.setCarInfo(res);
            returnDto.setPlateId(reqDto.getPlateId());
            return Result.success(returnDto);
        } else {
            return Result.failed("获取车辆信息失败！请联系管理员");
        }
    }

    /**
     * 反馈车辆信息提交
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<PostCarInfoResultDto> postCarInfo(PostCarInfoReqDto reqDto) {
        //提交前需要保存车辆信息
        PlateVehicle plateVehicle = plateVehicleMapper.selectById(reqDto.getPlateId());
        CarInfoDto carInfo = reqDto.getCarInfo();
        Result<UserResDto> result = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!result.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        if (plateVehicle != null) {
            BeanUtils.copyProperties(carInfo, plateVehicle);
            if (result != null && result.getData() != null && result.getData().getOrgVo() != null) {
                plateVehicle.setUpdateBy(result.getData().getNickname());
            }
            plateVehicle.setUpdateId(reqDto.getUid());
            plateVehicle.setUpdateTime(LocalDateTime.now());
            plateVehicleMapper.updateById(plateVehicle);
        } else {
            plateVehicle = new PlateVehicle();
            BeanUtils.copyProperties(carInfo, plateVehicle);
            plateVehicle.setId(reqDto.getPlateId());
            plateVehicle.setCreateTime(LocalDateTime.now());
            plateVehicle.setCreateId(reqDto.getUid());
            if (result != null && result.getData() != null) {
                plateVehicle.setCreateBy(result.getData().getNickname());
            }
            plateVehicleMapper.insert(plateVehicle);
        }


        // 更新Plate表的车牌号
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        if (plate != null && plate.getTradeAppId() != null) {
            //如果当前车牌号发生了变化则更新
            if (StringHelper.isEmpty(plate.getPlateNumber()) || !plate.getPlateNumber().equals(carInfo.getLicensePlate())) {
                plate.setPlateNumber(carInfo.getLicensePlate());
                plate.setUpdateTime(LocalDateTime.now());
                if (result != null && result.getData() != null && result.getData().getOrgVo() != null) {
                    plate.setUpdateBy(result.getData().getNickname());
                }
                plate.setUpdateId(reqDto.getUid());
                plateMapper.updateById(plate);
            }
        } else {
            return Result.failed("包车牌信息不存在，请联系管理员！");
        }

        PlateOwner existPlateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        if (existPlateOwner == null) {
            return Result.failed("包车牌业户信息不存在，请联系管理员！");
        }
        PlateLine plateLine = plateLineMapper.selectById(reqDto.getPlateId());
        if (plateLine == null) {
            return Result.failed("包车牌运次信息不存在，请联系管理员！");
        }

        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setBusInfo(reqDto, plate, existPlateOwner, plateLine)), CharterApplyLicense.SUBMIT_VEHICLE_URL);
        if ("200".endsWith(map.get("code"))) {
            JSONObject obj = JSONObject.parseObject(map.get("data"));
            //说明返回的信息是刚才申请的车辆信息  写入刚才这辆车
            if (carInfo.getVehicleId().equals(obj.get("vehicleid"))) {
                plateVehicle = plateVehicleMapper.selectById(reqDto.getPlateId());
                plateVehicle.setAnnexName(obj.getString("annexname"));
                plateVehicle.setAnnexType(obj.getString("annextype"));
                plateVehicle.setStorageAddress(obj.getString("storageaddress"));
                plateVehicle.setUpdateTime(LocalDateTime.now());
                plateVehicle.setUpdateId(reqDto.getUid());
                if (result != null && result.getData() != null && result.getData().getOrgVo() != null) {
                    plateVehicle.setUpdateBy(result.getData().getNickname());
                }
                plateVehicleMapper.updateById(plateVehicle);
            }

            PostCarInfoResultDto postCarInfoResultDto = JsonHelper.deserialize(map.get("data"), PostCarInfoResultDto.class);
            postCarInfoResultDto.setPlateId(reqDto.getPlateId());
            // TODO: 2025/9/25 后续可以考虑是否写入对应车辆下车辆信息，通过车辆ID去匹配？是否存在多个
            return Result.success(postCarInfoResultDto);
        } else {
            return Result.failed(map.get("data"));
        }
    }

    /**
     * 组装车辆信息
     *
     * @return
     */
    private Map<String, Object> setBusInfo(PostCarInfoReqDto postCarInfoReqDto, Plate plate, PlateOwner plateOwner, PlateLine plateLine) {
        CarInfoDto reqDto = postCarInfoReqDto.getCarInfo();
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("licenseno_yh", plateOwner.getLiceno());
        jsonParam.put("limitstart_xl", plateLine.getLimitStart().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        jsonParam.put("limitend_xl", plateLine.getLimitEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        jsonParam.put("totalmileage_xl", plateLine.getTotalMileage());
        jsonParam.put("manUnitCode", reqDto.getManUnitCode());
        jsonParam.put("manUnitCodeName", reqDto.getManUnitCodeName());
        jsonParam.put("indexno", reqDto.getIndexNo());
        jsonParam.put("colorName", reqDto.getColorName() == null ? "" : reqDto.getColorName());
        jsonParam.put("crllxName", reqDto.getCrllxName() == null ? "" : reqDto.getCrllxName());
        jsonParam.put("genreName", reqDto.getGenreName() == null ? "" : reqDto.getGenreName());
        jsonParam.put("technicalgradeName", reqDto.getTechnicalGradeName() == null ? "" : reqDto.getTechnicalGradeName());
        jsonParam.put("typeclasses", reqDto.getTypeClasses());
        jsonParam.put("typeclassesName", reqDto.getTypeClassesName());
        //需要去运次信息表查询车牌类型
        jsonParam.put("licPlaTypeinfo", plateLine.getLicplatype());
        jsonParam.put("limitStart", DateHelper.getNow());
        jsonParam.put("limitEnd", DateHelper.getNow());
        jsonParam.put("vehicleid", reqDto.getVehicleId());
        jsonParam.put("cClId", reqDto.getCciid() == null ? "" : reqDto.getCciid());
        jsonParam.put("appid", plate.getTradeAppId());
        jsonParam.put("cccnf", reqDto.getCccnf());
        jsonParam.put("ccjh", reqDto.getCcjh());
        jsonParam.put("ccp", reqDto.getCcp());
        jsonParam.put("color", reqDto.getColor());
        jsonParam.put("crllx", reqDto.getCrllx());
        jsonParam.put("cyxzzrq", reqDto.getCyxzzrq());
        jsonParam.put("djjbnx", reqDto.getDjjbnx());
        jsonParam.put("genre", reqDto.getGenre());
        jsonParam.put("isgps", reqDto.getIsGps() == null ? 0 : reqDto.getIsGps());
//        jsonParam.put("isgps", 1);
        jsonParam.put("issecuritycheck", reqDto.getIsSecurityCheck() == null ? 0 : reqDto.getIsSecurityCheck());
//        jsonParam.put("issecuritycheck", 1);
        jsonParam.put("jsjbnx", reqDto.getJsjbnx());
        jsonParam.put("licenseplate", reqDto.getLicensePlate());
        jsonParam.put("limitcheck", reqDto.getLimitCheck());
        jsonParam.put("limitplay", reqDto.getLimitPlay());
        jsonParam.put("lineid", plateLine.getLineId());
        jsonParam.put("maintain", reqDto.getMaintain() == null ? DateHelper.getNow() : reqDto.getMaintain());
        jsonParam.put("mark", reqDto.getMark() == null ? "" : reqDto.getMark());
        jsonParam.put("seat", reqDto.getSeat());
        jsonParam.put("secupers", reqDto.getSecupers() == null ? "" : reqDto.getSecupers());
        jsonParam.put("technicalgrade", reqDto.getTechnicalGrade());
        jsonParam.put("technicalgradeName", reqDto.getTechnicalGradeName());
        jsonParam.put("transportation", reqDto.getTransportation());
        jsonParam.put("trip", reqDto.getTrip() == null ? 0 : reqDto.getTrip());
        jsonParam.put("typeclasses", reqDto.getTypeClasses());
        jsonParam.put("typeclassesName", reqDto.getTypeClassesName() == null ? "" : reqDto.getTypeClassesName());
        jsonParam.put("vehicleproducts", reqDto.getVehicleProducts() == null ? "" : reqDto.getVehicleProducts());
        jsonParam.put("filepath", reqDto.getFilePath() == null ? "" : reqDto.getFilePath());
        jsonParam.put("remarks", reqDto.getRemarks() == null ? "" : reqDto.getRemarks());
        jsonParam.put("vehicleCanRelationBaoCheIndex", true);
//        jsonParam.put("indexno", "");
        return jsonParam;
    }


    @Override
    public Result<PlateLineInfoResultDto> getTransportatinCycle(GetTransportatinCycleReq reqDto) {
        //如果存在plateId直接从数据库查询，可能是上一步不是点回车获取信息直接填充
        PlateLine existPlateLine = plateLineMapper.selectById(reqDto.getPlateId());
        if (existPlateLine != null) {
            PlateLineDto res = new PlateLineDto();
            ObjectHelper.writeWithFrom(res, existPlateLine);

            PlateLineInfoResultDto plateLineInfoResultDto = new PlateLineInfoResultDto();
            plateLineInfoResultDto.setPlateLineInfo(res);
            plateLineInfoResultDto.setPlateId(reqDto.getPlateId());
            return Result.success(plateLineInfoResultDto);
        } else {
            return Result.failed("获取失败");
        }
    }

    /**
     * 组装运次信息
     *
     * @throws PostPlateLineReqDto
     */
    private Map<String, Object> setTransportatinCycleValue(PostPlateLineReqDto postPlateLineReqDto, Plate plate) {
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("appid", plate.getTradeAppId() == null ? "" : plate.getTradeAppId());
        PlateLineDto reqDto = postPlateLineReqDto.getPlateLineInfo();
        jsonParam.put("lineid", reqDto.getLineId() != null ? reqDto.getLineId() : "");
        jsonParam.put("departure", reqDto.getDeparture() != null ? reqDto.getDeparture() : "");
        jsonParam.put("theend", reqDto.getTheend() != null ? reqDto.getTheend() : "");
        jsonParam.put("company", reqDto.getCompany());
        jsonParam.put("lictype", reqDto.getLicType());
        jsonParam.put("matter", reqDto.getMatter());
        jsonParam.put("perno", reqDto.getPerno() != null ? reqDto.getPerno().toString() : "");
        DateHelper.getDateTime(reqDto.getLimitStart());
        jsonParam.put("limitstart", reqDto.getLimitStart() == null ? "" : reqDto.getLimitStart().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        jsonParam.put("limitend", reqDto.getLimitEnd() == null ? "" : reqDto.getLimitEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        jsonParam.put("departureaddress", reqDto.getStartPlace());
        jsonParam.put("theendaddress", reqDto.getEndPlace());
        jsonParam.put("waylineaddress", reqDto.getWayLineAddress());
        jsonParam.put("isreturn", reqDto.getIsreturn());
        jsonParam.put("totalmileage", reqDto.getTotalMileage() != null ? reqDto.getTotalMileage().toString() : "");
        jsonParam.put("highmileage", reqDto.getHighMileage() != null ? reqDto.getHighMileage().toString() : "");
        jsonParam.put("auditcounties", reqDto.getAuditCounties());
        jsonParam.put("cardtype", reqDto.getCardType());
        jsonParam.put("licplatype", reqDto.getLicplaType());
        jsonParam.put("remarks", reqDto.getRemarks());

        PlateOwner plateOwner = plateOwnerMapper.selectById(postPlateLineReqDto.getPlateId());
        if (plateOwner != null) {
            jsonParam.put("kyclnum", plateOwner.getKyNum() != null ? plateOwner.getKyNum().toString() : "");
            jsonParam.put("kyclnumzws", plateOwner.getKyzwNum() != null ? plateOwner.getKyzwNum().toString() : "");
        } else {
            jsonParam.put("kyclnum", "");
            jsonParam.put("kyclnumzws", "");
        }

        jsonParam.put("wayline", reqDto.getWayLine() != null ? reqDto.getWayLine() : "");
        jsonParam.put("waylinecode", reqDto.getWayLineCode() != null ? reqDto.getWayLineCode() : "");
        return jsonParam;
    }

    /**
     * 根据业户ID和驾驶员从业资格证查询驾驶员信息
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<GetDriveInfoReturnDto> getDriverInfo(DriverInfoReqDto reqDto) {
        Map<String, Object> stringObjectMap = new HashMap<>();
        //从业资格证号码跟身份证号码是一个
        stringObjectMap.put("cardno", reqDto.getCardNo());
        PlateOwner plateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        PlateVehicle plateVehicle = plateVehicleMapper.selectById(reqDto.getPlateId());
        if (plateVehicle != null && plateOwner != null && !StringHelper.isEmpty(plateOwner.getLiceno())) {
            stringObjectMap.put("licenseno_yh", plateOwner.getLiceno());
        } else {
            return Result.failed("获取车辆信息异常！");
        }
        // 调用外部接口获取驾驶员信息
        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(stringObjectMap), CharterApplyLicense.GET_DRIVERINFO_URL);
        if ("200".endsWith(map.get("code"))) {
            DriveInfoResultDto data = JSON.parseObject(map.get("data"), DriveInfoResultDto.class);
            DriverInfoDto driverInfoDto = new DriverInfoDto();
            if (data.getAppDriverQueryList() != null && !data.getAppDriverQueryList().isEmpty()) {
                ObjectHelper.writeWithFrom(driverInfoDto, data.getAppDriverQueryList().get(0));
                ObjectHelper.writeWithFrom(driverInfoDto, data);
            }
            GetDriveInfoReturnDto getDriveInfoReturnDto = new GetDriveInfoReturnDto();
            getDriveInfoReturnDto.setDriverInfo(driverInfoDto);
            getDriveInfoReturnDto.setPlateId(reqDto.getPlateId());
            return Result.success(getDriveInfoReturnDto);
        } else {
            return Result.failed(map.get("data"));
        }
    }

    /**
     * 通过包车牌主键id查询驾驶员信息
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<GetDriveInfoReturnDto2> getDriverInfo2(DriverInfoReq2Dto reqDto) {
        //驾驶员是查出多个
        List<PlateDriver> driverList = plateDriverMapper.selectList(new LambdaQueryWrapper<PlateDriver>().eq(PlateDriver::getPlateId, reqDto.getPlateId()));
        GetDriveInfoReturnDto2 returnDto2 = new GetDriveInfoReturnDto2();
        if (driverList != null && !driverList.isEmpty()) {
            List<DriverInfoDto> driverInfoDtos = ConvertUtil.copyList(driverList, DriverInfoDto.class);
            returnDto2.setDrivers(driverInfoDtos);
        } else {
            returnDto2.setDrivers(new ArrayList<>());
        }
        returnDto2.setPlateId(reqDto.getPlateId());
        return Result.success(returnDto2);
    }

    /**
     * 反馈驾驶员信息提交
     * 需要行业校验通过才能保存驾驶员
     *
     * @param reqDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<PostDriverInfoResultDto> postDriver(PostDriverInfoReqDto reqDto) {
        //获取用户相关信息
        Result<UserResDto> result = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!result.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        List<DriverInfoDto> drivers = reqDto.getDrivers();
        //业户信息
        PlateOwner plateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        // 更新Plate表的驾驶员姓名 增加驾驶员
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        //线路信息
        PlateLine plateLine = plateLineMapper.selectById(reqDto.getPlateId());
        //车辆信息
        PlateVehicle plateVehicle = plateVehicleMapper.selectById(reqDto.getPlateId());
        if (plate == null || plateOwner == null || plateLine == null || plateVehicle == null || StringHelper.isEmpty(plateOwner.getLiceno()) || StringHelper.isEmpty(plateVehicle.getVehicleId())) {
            return Result.failed("包车牌不存在！");
        }

        // 如果已有驾驶员姓名，则追加，否则设置
        String existingDriverName = plate.getDriverName();

        //批量更新保存驾驶员信息
        for (DriverInfoDto driverInfo : drivers) {
            //通过包车牌id和驾驶员id
            PlateDriver plateDriver = plateDriverMapper.selectOne(new LambdaQueryWrapper<PlateDriver>().eq(PlateDriver::getPlateId, reqDto.getPlateId()).eq(PlateDriver::getDriverId, driverInfo.getDriverId()));

            //组装驾驶员信息
            if (existingDriverName != null && !existingDriverName.isEmpty()) {
                if (!existingDriverName.contains(driverInfo.getAppDriverName())) {
                    existingDriverName = existingDriverName + "," + driverInfo.getAppDriverName();
                }
            } else {
                existingDriverName = driverInfo.getAppDriverName();
            }

            if (plateDriver != null) {
                ObjectHelper.writeWithFrom(plateDriver, driverInfo);
                plateDriver.setUpdateTime(LocalDateTime.now());
                if (result != null && result.getData() != null && result.getData().getOrgVo() != null) {
                    plateDriver.setUpdateBy(result.getData().getNickname());
                }
                plateDriver.setUpdateId(reqDto.getUid());
                plateDriverMapper.updateById(plateDriver);
            } else {
                plateDriver = new PlateDriver();
                ObjectHelper.writeWithFrom(plateDriver, driverInfo);
                plateDriver.setPlateId(reqDto.getPlateId());
                plateDriver.setCreateTime(LocalDateTime.now());
                plateDriver.setCreateId(reqDto.getUid());
                if (result != null && result.getData() != null) {
                    plateDriver.setCreateBy(result.getData().getNickname());
                }
                plateDriverMapper.insert(plateDriver);
            }
        }

        plate.setDriverName(existingDriverName);
        plate.setUpdateTime(LocalDateTime.now());
        if (result != null && result.getData() != null) {
            plate.setUpdateBy(result.getData().getNickname());
        }
        plate.setUpdateId(reqDto.getUid());
        plateMapper.updateById(plate);

        // 记录错误信息
        StringBuilder errorUpdateDriverInfo = new StringBuilder();
        //批量推送驾驶员信息
        for (DriverInfoDto driverInfo : drivers) {
            Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setDriverInfo(reqDto, driverInfo, plateOwner, plateLine, plateVehicle)), CharterApplyLicense.SUBMIT_DRIVER_URL);
            if ("200".endsWith(map.get("code"))) {
                JSONObject obj = JSONObject.parseObject(map.get("data"));
                // 更新驾驶员信息表中的附件信息
                PlateDriver plateDriver = plateDriverMapper.selectOne(new LambdaQueryWrapper<PlateDriver>().eq(PlateDriver::getPlateId, reqDto.getPlateId()).eq(PlateDriver::getDriverId, driverInfo.getDriverId()));
                if (plateDriver != null) {
                    plateDriver.setAnnexName(obj.getString("annexname"));
                    plateDriver.setAnnexType(obj.getString("annextype"));
                    plateDriver.setStorageAddress(obj.getString("storageaddress"));
                    plateDriver.setDriverId(obj.getInteger("driverid"));
                    plateDriver.setUpdateTime(LocalDateTime.now());
                    plateDriverMapper.updateById(plateDriver);
                }
            } else {
                // 解析错误代码code
                if (map.get("code").equals("900")) {
                    if (errorUpdateDriverInfo.length() > 0) {
                        errorUpdateDriverInfo.append("," + driverInfo.getAppDriverName() + map.get("data"));
                    } else {
                        errorUpdateDriverInfo.append(driverInfo.getAppDriverName() + map.get("data"));
                    }
                }
            }
        }
        if (errorUpdateDriverInfo.length() > 0) {
            return Result.success(new PostDriverInfoResultDto(reqDto.getPlateId()));
        } else {
            return Result.failed(errorUpdateDriverInfo.toString());
        }
    }

    /**
     * 组装驾驶员信息
     *
     * @param reqDto
     * @return
     */
    private Map<String, Object> setDriverInfo(PostDriverInfoReqDto reqDto, DriverInfoDto driverInfo, PlateOwner plateOwner, PlateLine plateLine, PlateVehicle plateVehicle) {
        JSONObject jsonParam = new JSONObject();
        // 从包车牌主表查询appId
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        jsonParam.put("appdrivername", driverInfo.getAppDriverName());
        if (plate != null) {
            jsonParam.put("appid", plate.getTradeAppId());
        } else {
            jsonParam.put("appid", "");
        }
        jsonParam.put("bagsIsRight", driverInfo.getBagsIsRight());
        jsonParam.put("cCxfz", driverInfo.getCcxfz());
        jsonParam.put("cCxkhdj", driverInfo.getCcxkhdj());
        jsonParam.put("cCyzt", driverInfo.getCcyzt());
        jsonParam.put("cid", driverInfo.getCid());
        jsonParam.put("cJszClrq", driverInfo.getCjszclrq());
        jsonParam.put("cWhcd", driverInfo.getCwhcd());
        jsonParam.put("cWhcdName", driverInfo.getCwhcdName());
        jsonParam.put("cXckhrq", driverInfo.getCxckhrq());
        jsonParam.put("cYfw", driverInfo.getCyfw());
        jsonParam.put("cZgzClrq", driverInfo.getCzgzclrq());
        jsonParam.put("cZjcx", driverInfo.getCzjcx());
        jsonParam.put("cZjcxName", driverInfo.getCzjcxName());
        jsonParam.put("cardno", driverInfo.getCardNo());
        jsonParam.put("driveage", driverInfo.getDriveage());
        jsonParam.put("driverAddOrUpdate", driverInfo.getDriverAddOrUpdate() == 1 ? "true" : "false");
        jsonParam.put("driverAndTime", driverInfo.getDriverAndTime());
        jsonParam.put("driverid", driverInfo.getDriverId());
        jsonParam.put("engage", driverInfo.getEngage() == null ? DateHelper.getNow() : driverInfo.getEngage());
        jsonParam.put("filepath", driverInfo.getFilePath() == null ? "" : driverInfo.getFilePath());
        jsonParam.put("haveDriverNum", driverInfo.getHaveDriverNum());
        jsonParam.put("ismaindrive", driverInfo.getIsMainDrive() == null ? "" : driverInfo.getIsMainDrive());
        //业户号
        jsonParam.put("licenseno_yh", plateOwner.getLiceno());
        //车牌号
        jsonParam.put("licenseplate_cl", plateVehicle.getLicensePlate());
        jsonParam.put("limitend", driverInfo.getLimitEnd());
        //线路使用期限：结束日期
        jsonParam.put("limitend_xl", plateLine.getLimitEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        jsonParam.put("limitstart", driverInfo.getLimitStart());
        //线路使用期限：开始时间
        jsonParam.put("limitstart_xl", plateLine.getLimitStart().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        jsonParam.put("ownerlicenseno", driverInfo.getOwnerLicenseNo());
        jsonParam.put("ownername", driverInfo.getOwnerName());
        jsonParam.put("qualification", driverInfo.getQualification());
        jsonParam.put("situation", driverInfo.getSituation() == null ? "" : driverInfo.getSituation());
        jsonParam.put("telephone", driverInfo.getTelephone());
        jsonParam.put("vehicleid", plateVehicle.getVehicleId());
        jsonParam.put("remarks", driverInfo.getRemarks() == null ? "" : driverInfo.getRemarks());
        return jsonParam;
    }

    public static void main(String[] args) {

        Map<String, Object> paramMap = new HashMap<>();
        // 获取省// 获取省
        paramMap.put("PrintLicPlaID", 11);
        paramMap.put("filepaTh", "2222");
        GenerateCharterPlateReturnDto deserialize = JsonHelper.deserialize(JsonHelper.serialize(paramMap), GenerateCharterPlateReturnDto.class);

        System.out.println("---");

//        String ss = "{\"plateId\":\"12\",\"plateOwnerInfo\":{\"liceno\":\"500102900142\",\"ownerId\":379882,\"cardBeginDate\":\"2025-04-08 15:36:13\",\"cardEndDate\":\"2029-04-08 15:36:13\",\"address\":\"重庆市涪陵区兴华花园B区5号二楼\",\"ownerName\":\"重庆涪陵天龙客运出租有限公司第一分公司\",\"operateRange\":\"县内包车客运,县内班车客运\",\"economicType\":\"90010014\",\"examrank\":\"\",\"kyNum\":7,\"kyzwNum\":207,\"gjNum\":\"20001115\",\"gjzwNum\":60,\"zjNum\":5,\"zjzwNum\":147,\"chargerName\":\"关新耀\",\"contactTel\":\"13896568833\",\"manunitCode\":\"500102\"}}";
//
//        PlateOwnerPostReqDto deserialize = JsonHelper.deserialize(ss, PlateOwnerPostReqDto.class);
//        System.out.println("---");
//        PlateOwnerPostReqDto res = new PlateOwnerPostReqDto();
//        res.setPlateId(1L);
//        PlateOwnerDto plateOwnerDto = new PlateOwnerDto();
//        plateOwnerDto.setAddress("测试这");
//        res.setPlateOwnerInfo(plateOwnerDto);
//        System.out.println(JsonHelper.serialize(res));

//        Map<String, Object> paramMap = new HashMap<>();
//        // 获取省// 获取省
////        paramMap.put("cLevel", "00550001");
////        paramMap.put("id", "");
//
////        paramMap.put("cLevel", "");
////        paramMap.put("id", "10000003");
////        paramMap.put("Code", "10000003");
////        paramMap.put("annexname", "10000003");
////        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(paramMap), CharterApplyLicense.GET_CITIESDJ);
////        System.out.println(map.get("data"));
////
////        String ss = JSON.toJSONString(paramMap);
////        System.out.println(ss);
////        PostCarInfoResultDto postCarInfoResultDto1 = JSON.parseObject(ss, PostCarInfoResultDto.class);
////        System.out.println(map.get("data"));
////        PostCarInfoResultDto postCarInfoResultDto = new PostCarInfoResultDto();
////        PostCarInfoResultDto o = JSON.parseObject(JSON.toJSONString(paramMap), PostCarInfoResultDto.class);
////        System.out.println(map.get("data"));
//
//        System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
//        // 查询当天该商家的最大编号（按字典序）
//        System.out.println(String.format("%04d", 1));
//        List<String> list = new ArrayList<>();
//        list.add("11");
//        list.add("22");
//        list.add("33");
//        System.out.println(JsonHelper.serialize(list));
//        String ss = "[\"11\",\"22\",\"33\"]";
////        Test deserialize = JsonHelper.deserialize(JsonHelper.serialize(list), Test.class);
//        System.out.println();
//        System.out.println(222);
//
//        PlateOwner plateOwner;
//        PlateOwnerDto copy = ConvertUtil.copy(null, PlateOwnerDto.class);
//        System.out.println(copy);
//
//        System.out.println(CharterPlateTypeEnum.get("00030008").getCode());
//        System.out.println(CharterPlateTypeEnum.get("00030008").getDescription());
//
//        String result = "{\"code\":\"200\",\"data\":\"82751beb8c7823d940a365c9fa79c155815f6156d7a4fcf6579116b5e9e1030912108967aa786c5824eb4b4949773d9524c5ed72a5237584c6f8a77fb554cfc4a0e6ef2875a900dde3cf4f1350fc6340d0030f633226556c4a24c97a98f166954daedec1d8d96976a3ee00633f2afd21af767a040c3141f381ac30c628bc52583437058bbfa57bb4e15822869b88d7c56f3ba7c82c504700cdbe292adf2bf07d3b8a03c9b550059da994c2a6bbbf8e0432918e5d61b8fbcc83fae424f5500972de138ec4bbf0b1b0e7519de38038ecf5\",\"desc\":\"操作成功\"}";
//
//        Map<String, String> stringStringMap = CharterApplyLicense.receiveCharterLicenseData(RtabTokenHelper.KEY, result);
//        System.out.println(JsonHelper.serialize(stringStringMap));
    }

    /**
     * 分页查询包车牌信息
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<?> getPlatePageList(PlatePageReqDto reqDto) {
        // 创建分页对象
        //第3种方式  调用 mapper的selectPage查询然后在转换为PageInfo对象
        LambdaQueryWrapper<Plate> eq = new LambdaQueryWrapper<Plate>().eq(Plate::getOrgId, reqDto.getUid())
                .eq(StringUtils.isNotBlank(reqDto.getDriverName()), Plate::getDriverName, reqDto.getDriverName());
        Page<Plate> page = new Page<>(reqDto.getPageNum(), reqDto.getPageSize());
        Page<Plate> platePage = plateMapper.selectPage(page, eq);
        return Result.success(platePage.getRecords(), platePage.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> deleteDriver(DelDriverReqDto reqDto) {
        // 提交前需要保存驾驶员信息
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        if (plate == null) {
            return Result.failed("该包车牌信息不存在");
        } else {
            if (plate.getTradeAppId() == null) {
                return Result.failed("该包车牌信息未关联业务");
            }
        }


        JSONObject reqParams = new JSONObject();
        reqParams.put("appid", plate.getTradeAppId());
        reqParams.put("driverid", reqDto.getDriverId());

        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(reqParams), CharterApplyLicense.DELETE_DRIVER_URL);
        if ("200".endsWith(map.get("code"))) {
            JSONObject obj = JSONObject.parseObject(map.get("data"));
            // 更新驾驶员信息表中的附件信息
            if (obj.get("RTBASEPROCESS001") != null && obj.get("RTBASEPROCESS001").equals("删除成功")) {
                updateDriverInfo(reqDto, plate);
                return Result.success("删除成功！");
            } else if (obj.get("RTBASEPROCESS002") != null) {
                // 该驾驶员在提交到运管系统的信息不存在，则逻辑删除本地数据库的提交请求记录
                updateDriverInfo(reqDto, plate);
                return Result.success("删除成功！");
            }
            return Result.success(JSON.parseObject(map.get("data"), PostDriverInfoResultDto.class));
        } else {
            return Result.failed(map.get("data"));
        }
    }

    /**
     * 更新驾驶员信息
     *
     * @param reqDto
     * @param plate
     */
    public void updateDriverInfo(DelDriverReqDto reqDto, Plate plate) {
        PlateDriver plateDriver = plateDriverMapper.selectOne(new LambdaQueryWrapper<PlateDriver>().eq(PlateDriver::getPlateId, reqDto.getPlateId()).eq(PlateDriver::getDriverId, reqDto.getDriverId()));
        //更新驾驶员信息
        String driverName = Arrays.stream(plate.getDriverName().split(","))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .filter(s -> !s.equals(plateDriver.getAppDriverName()))
                .collect(Collectors.joining(","));
        plate.setDriverName(driverName);
        plateMapper.updateById(plate);
        //删除驾驶员
        plateDriverMapper.delete(new LambdaQueryWrapper<PlateDriver>().eq(PlateDriver::getPlateId, reqDto.getPlateId()).eq(PlateDriver::getDriverId, reqDto.getDriverId()));
        //删除驾驶员附件
        plateAnnexMapper.delete(new LambdaQueryWrapper<PlateAnnex>().eq(PlateAnnex::getPlateId, reqDto.getPlateId()).eq(PlateAnnex::getAnnexSort, reqDto.getDriverId()));
    }


    @Override
    public Result<?> getCooperateCode(BaseUserReqDto reqDto) {
        Result<UserResDto> result = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!result.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        if (result != null && result.getData() != null && result.getData().getOrgVo() != null && !StringHelper.isEmpty(result.getData().getOrgVo().getMerchantCode())) {
            Result<List> allMerchantInfo = merchantFeignClient.getAllMerchantInfo(MerchantReqDto.builder().merchantCode(result.getData().getOrgVo().getMerchantCode()).build());
            if (allMerchantInfo != null && allMerchantInfo.getData() != null && !allMerchantInfo.getData().isEmpty() && !StringHelper.isEmpty(((LinkedHashMap) allMerchantInfo.getData().get(0)).get("cooperateCode"))) {
                Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(new PlateOwnerReqDto(((LinkedHashMap) allMerchantInfo.getData().get(0)).get("cooperateCode").toString())), CharterApplyLicense.GET_OWNER_INFO);
                if ("200".endsWith(map.get("code"))) {
                    return Result.success(JSON.parseObject(JSON.toJSONString(getValue(map.get("data"))), PlateOwnerDto.class));
                } else {
                    return Result.failed(map.get("data"));
                }
            }
        }
        return Result.failed("该商户没有道路经营许可证");
    }

    @Override
    public Result<?> test(String ss) {
        Plate plate = plateMapper.selectById(9);
        plate.setOrgName(ss);
        plateMapper.updateById(plate);

        if (plate != null && StringHelper.isEmpty(plate.getTradeAppId())) {
            plate.getOrgName();
            System.out.println("这是空的");
        }
        return Result.success(plateMapper.selectNextSequence("1010"));
    }

    /**
     * 分页查询包车牌信息
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<?> getPlateDraftPageList(PlateDraftPageReqDto reqDto) {
        resetReqDto(reqDto);
        // 创建分页对象
        UserResDto user = UserSessionManager.getMerchantUser(reqDto.getUid());
        // 分页
        startPage(reqDto.getPageNum(), reqDto.getPageSize());

        PlateDraftPageResultDto2 plateDraftPageResultDto2 = new PlateDraftPageResultDto2();
        plateDraftPageResultDto2.setPlates(plateMapper.selectPlateDraftPage(reqDto));

        PlateCountResultDto plateCountResult = plateMapper.countPlateStatistics(reqDto);
        ObjectHelper.writeWithFrom(plateDraftPageResultDto2, plateCountResult);

        return Result.success(plateDraftPageResultDto2, new PageInfo<>(plateDraftPageResultDto2.getPlates()).getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> delPlateDraft(DelPlateDraftReqDto reqDto) {
        // 获取要删除的ID列表
        List<Long> ids = reqDto.getIds();

        // 判断ID列表是否为空
        if (ids == null || ids.isEmpty()) {
            return Result.failed("删除ID列表不能为空");
        }

        // 批量查询包车牌数据
        List<Plate> plates = plateMapper.selectBatchIds(ids);

        // 过滤出草稿状态的数据（charterPlateStatus = 0 表示草稿）
        List<Plate> draftPlates = plates.stream()
                //根据id删除所有
//                .filter(plate -> plate.getCharterPlateStatus() == 0)
                .collect(Collectors.toList());

        // 检查是否有非草稿状态的数据
        if (draftPlates.size() != plates.size()) {
            log.warn("尝试删除非草稿状态的数据，已自动过滤");
        }

        // 判断是否有可删除的数据
        if (draftPlates.isEmpty()) {
            return Result.failed("没有可删除的草稿数据");
        }

        Result<UserResDto> result = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!result.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        // 批量更新删除标志
        LocalDateTime now = LocalDateTime.now();
        List<Plate> updatePlates = draftPlates.stream().map(plate -> {
            plate.setDelFlag("1");
            plate.setUpdateTime(now);
            plate.setUpdateId(reqDto.getUid());
            plate.setUpdateBy(result.getData().getNickname());
            return plate;
        }).collect(Collectors.toList());

        // 使用 MyBatis-Plus 的 updateBatchById 方法（如果可用）
        // 或者逐个更新
        int successCount = 0;
        for (Plate plate : updatePlates) {

            //TODO 2025/10/21 推送运管删除草稿
            if (!StringHelper.isEmpty(plate.getTradeAppNumber())) {
                JSONObject jsonParam = new JSONObject();
                jsonParam.put("appNumber", plate.getTradeAppNumber());
                Map<String, String> stringStringMap = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(jsonParam), CharterApplyLicense.MTA_DELETE_DRAFT);
                log.info("运管系统执行删除编号为{} 的包车牌草稿数据，结果{}", plate.getTradeAppNumber(), stringStringMap.get("data"));
            }

            if (plateMapper.updateById(plate) > 0) {
                successCount++;
            }
        }

        if (successCount > 0) {
            return Result.success("删除成功，共删除 " + successCount + " 条数据");
        } else {
            return Result.failed("删除失败");
        }
    }

    @Override
    public Result<?> operLogGet(OperLogGetReqDto reqDto) {
        // 1. 根据plateId查询操作日志列表
        LambdaQueryWrapper<PlateOperateLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PlateOperateLog::getPlateId, reqDto.getPlateId());
        queryWrapper.orderByDesc(PlateOperateLog::getCreateTime);
        List<PlateOperateLog> operateLogs = plateOperateLogMapper.selectList(queryWrapper);

        PlateOperLogGetReturnDto res = new PlateOperLogGetReturnDto();
        res.setPlateId(reqDto.getPlateId());
        if (operateLogs != null && !operateLogs.isEmpty()) {
            List<PlateOperLogDto> plateOperLogDtos = ConvertUtil.copyList(operateLogs, PlateOperLogDto.class);
            res.setPlateOperLogs(plateOperLogDtos);
        } else {
            res.setPlateOperLogs(new ArrayList<>());
        }
        // 2. 返回结果
        return Result.success(res);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<?> savePlateSign(PlateSaveReqDto reqDto) {
        Long plateId = reqDto.getPlateId();
        RLock lock = null;
        try {
            lock = redissonClient.getLock(OrderLockUtils.getLockKey(plateId));
            if (!lock.tryLock(OrderLockUtils.LOCK_WAIT_TIME_SECOND, TimeUnit.SECONDS)) {
                log.info("savePlateSign-签发操作失败：{}", reqDto);
                return Result.failed("签发操作失败");
            }
            // 插入成功
            return doSavePlateSign(reqDto);
        } catch (Exception e) {
            log.error("签发操作失败：{}", reqDto, e);
            if (e instanceof BusinessException) {
                throw (BusinessException) e;
            }
            throw new BusinessException("签发操作失败");
        } finally {
            if (Objects.nonNull(lock) && lock.isLocked()) {
                lock.unlock();
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Result<?> doSavePlateSign(PlateSaveReqDto reqDto) {
        Result<UserResDto> result = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!result.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        //包车牌信息
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        //业户信息表
        PlateOwner plateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());

        if (plate == null || plateOwner == null || StringHelper.isEmpty(plateOwner.getLiceno())) {
            return Result.failed("该包车牌信息不存在！");
        }

        if (plate.getCharterPlateStatus() != CharterPlateStatusEnum.SIGN.getCode() || plate.getCharterPlateStatus() != CharterPlateStatusEnum.REFILL.getCode()) {
            return Result.failed("该包车牌不是待签发或者打回重填状态！");
        }
        //更新包车牌表对应状态
        //签发状态(0:同意申请 1:驳回重填 2:终止申请)
        //包车牌状态 0：草稿 1：待签发 2：待审核 3：已审核未打印 4：已生成包车牌 5：已打印 6：已归档 7：作废重打 8：打回重填 9：已终止
        //操作日志记录保存
        if (reqDto.getSignStatus() == 0) {
            plate.setCharterPlateStatus(CharterPlateStatusEnum.REVIEW.getCode());
        } else if (reqDto.getSignStatus() == 1) {
            plate.setCharterPlateStatus(CharterPlateStatusEnum.REFILL.getCode());
            //驳回申请
        } else if (reqDto.getSignStatus() == 2) {
            plate.setCharterPlateStatus(CharterPlateStatusEnum.TERMINATED.getCode());
        }
//        todo 发送zz系统
        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setSaveOrAppove(plate, plateOwner, reqDto)), CharterApplyLicense.SAVE_ISSUE_OR_APPROVE);
        if ("200".endsWith(map.get("code"))) {
            //签发记录维护
            PlateSign plateSign = ConvertUtil.copy(reqDto, PlateSign.class);
            plateSign.setCreateId(reqDto.getUid());
            plateSign.setCreateBy(result.getData().getNickname());
            plateSign.setCreateTime(LocalDateTime.now());
            plateSignMapper.insert(plateSign);
            // 执行数据库写入
            plate.setUpdateId(reqDto.getUid());
            plate.setUpdateBy(result.getData().getNickname());
            plate.setUpdateTime(LocalDateTime.now());
            plateMapper.updateById(plate);

            // 新增日志记录
            super.addOperateLog(plate.getId(), reqDto.getUid(), reqDto.getSignStatus() == 0 ? OperateLogTempEnum.SIGN_APPLY : reqDto.getSignStatus() == 1 ? OperateLogTempEnum.REJECT_APPLY : OperateLogTempEnum.TERMINATE_APPLY, false);

            return Result.success("操作成功！");
        } else {
            return Result.failed(map.get("data"));
        }
    }

    /**
     * 签发操作
     *
     * @param reqDto
     * @return
     */
    public Map<String, Object> setSaveOrAppove(Plate plate, PlateOwner plateOwner, PlateSaveReqDto reqDto) {
        JSONObject reqParams = new JSONObject();
        reqParams.put("appno", plate.getTradeAppNumber());
        reqParams.put("applyPageType", "issue");
        reqParams.put("businesstype", "ffbc001");
        /**
         * 91190001	提交	91190005	打回重填
         * 91190002	取消流程	91190004	终止
         * 91190003	同意
         */
        if (reqDto.getSignStatus() == 0) {
            reqParams.put("taskStatus", "91190003");
        } else if (reqDto.getSignStatus() == 1) {
            reqParams.put("taskStatus", "91190005");
        } else if (reqDto.getSignStatus() == 2) {
            reqParams.put("taskStatus", "91190004");
        }
        reqParams.put("processType", "91180002");
        reqParams.put("applyOrgcode", plateOwner.getLiceno());
        reqParams.put("operatorcode", plateOwner.getLiceno());
        reqParams.put("opinion", reqDto.getSignContent());
        return reqParams;
    }


    @Override
    public Result<PlateInfoGetResultDto> plateInfoGet(PlateInfoGetReqDto reqDto) {
        PlateInfoGetResultDto result = new PlateInfoGetResultDto();
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        if (plate != null) {
            ObjectHelper.writeWithFrom(result, plate);
        } else {
            Result.failed("获取包车牌信息失败！");
        }
        //驾驶员是查出多个
        result.setDrivers(ConvertUtil.copyList(plateDriverMapper.selectList(new LambdaQueryWrapper<PlateDriver>().eq(PlateDriver::getPlateId, reqDto.getPlateId())), DriverInfoDto.class));
        //业户信息
        result.setPlateOwner(ConvertUtil.copy(plateOwnerMapper.selectById(reqDto.getPlateId()), PlateOwnerDto.class));
        //车辆信息
        result.setCarInfoDto(ConvertUtil.copy(plateVehicleMapper.selectById(reqDto.getPlateId()), CarInfoDto.class));
        //线路信息
        result.setPlateLineInfo(ConvertUtil.copy(plateLineMapper.selectById(plate.getId()), PlateLineDto.class));
        //附件列表
        List<PlateAnnexDto> plateAnnexDtos = ConvertUtil.copyList(plateAnnexMapper.selectList(new LambdaQueryWrapper<PlateAnnex>().eq(PlateAnnex::getPlateId, reqDto.getPlateId())), PlateAnnexDto.class);
        //处理附件访问地址
        plateAnnexDtos.stream().forEach(plateAnnexDto -> {
            plateAnnexDto.setOssPath(fileUploadService.getFile(plateAnnexDto.getOssId()));
        });
        result.setPlateAnnexs(plateAnnexDtos);
        //包车牌id
        result.setPlateId(reqDto.getPlateId());
        return Result.success(result);
    }

    public Result<?> uploadFileAndStore2(UploadFileReqDto2 reqDto) {
        List<MultipartFile> multipartFiles = new ArrayList<>();
        for (UploadFileInfoDto uploadFileInfo : reqDto.getFiles()) {
            String file = fileUploadService.getFile(uploadFileInfo.getFileOssId());
            if (!StringHelper.isEmpty(file)) {
                byte[] fileBytes = HttpUtil.downloadBytes(file);
                // 使用uploadFileInfo中的文件名而不是OSS生成的文件名
                String originalFileName = uploadFileInfo.getFileName();
                // 创建MultipartFile对象
                MultipartFile multipartFile = new ByteArrayMultipartFile(
                        fileBytes,
                        originalFileName,
                        getContentType(originalFileName)
                );
                multipartFiles.add(multipartFile);
            }
        }
        // 现在multipartFiles列表包含了所有带有原始文件名的MultipartFile对象
        MultipartFile[] files = multipartFiles.toArray(new MultipartFile[0]);
        if (files.length == 0) {
            return Result.failed("请选择文件！");
        } else {
            UploadFileReqDto uploadFileReqDto = new UploadFileReqDto();
            ObjectHelper.writeWithFrom(uploadFileReqDto, reqDto);
            uploadFileReqDto.setFiles(files);
            return uploadFileAndStore(uploadFileReqDto);
        }
    }

    // 辅助方法：根据文件扩展名获取Content-Type
    private String getContentType(String fileName) {
        String extension = getFileExtension(fileName).toLowerCase();
        switch (extension) {
            case "pdf":
                return "application/pdf";
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            default:
                return "application/octet-stream";
        }
    }

    @Override
    public Result<?> uploadFileAndStore(UploadFileReqDto reqDto) {
        //先判断文件类型是否符合规范
        String fileName;
        String fileCode = "201";
        // 根据文件类型确定文件名
        switch (reqDto.getFileType()) {
            case "file0":
                fileName = "包车牌申请表.pdf";
                fileCode = "201";
                break;
            case "file1":
                fileName = "包车合同.pdf";
                fileCode = "202";
                break;
            case "file2":
                fileName = "行驶证.pdf";
                fileCode = "203";
                break;
            case "file3":
                fileName = "驾驶证.pdf";
                fileCode = "204";
                break;
            case "file4":
                fileName = "驾驶证-副驾.pdf";
                fileCode = "205";
                break;
            default:
                fileName = reqDto.getFiles()[0].getOriginalFilename(); // 默认文件名
        }

        Result<UserResDto> userInfo = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!userInfo.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        byte[] pdfBytes = null;
        String pdfFilePath = "";
        Boolean updateFlag;
        // 单文件处理

        try {
            if (reqDto.getFiles().length == 1) {
                MultipartFile file = reqDto.getFiles()[0];
                String fileExtension = getFileExtension(file.getOriginalFilename()).toLowerCase();
                // 如果是PDF文件，直接保存
                if ("pdf".equals(fileExtension)) {
                    pdfBytes = file.getBytes();
                    //如果是单个文件 先执行生成名字
                    fileName = file.getOriginalFilename();
                } else if (isImageFile(fileExtension)) {
                    // 如果是图片文件，转换为PDF
                    pdfBytes = convertMultipleImagesToPdf(reqDto.getFiles(), reqDto.getFileType());
                } else {
                    Result.failed("不支持的文件格式: " + fileExtension);
                }
            } else if (reqDto.getFiles().length > 1) {
                // 多文件处理 - 全部转换为PDF
                MultipartFile[] files = reqDto.getFiles();
                boolean allValid = Arrays.stream(files).allMatch(file -> isImageFile(getFileExtension(file.getOriginalFilename()).toLowerCase()));
                if (!allValid) {
                    return Result.failed("多文件上传时仅支持图片");
                }
                // 将多个文件（图片/PDF）合并为一个PDF
                pdfBytes = convertMultipleImagesToPdf(files, reqDto.getFileType());
            } else {
                return Result.failed("未上传任何文件");
            }

            // 创建临时文件
//            File tempFile = File.createTempFile("upload_", ".pdf");
//            FileUtils.writeByteArrayToFile(tempFile, pdfBytes);
//            System.out.println("临时文件保存成功：" + tempFile.getAbsolutePath());
        } catch (Exception e) {
            log.error("文件上传转换失败: {}", e.getMessage(), e);
            return Result.failed("文件转换异常");
        }
        if (!StringHelper.isEmpty(pdfBytes)) {
            //上传oss
            // 在 uploadFileAndStore 方法中直接使用
            // 在 uploadFileAndStore 方法中
            MultipartFile multipartFile = new ByteArrayMultipartFile(pdfBytes, fileName, "application/pdf");
            Result<?> result = fileUploadService.uploadOss(multipartFile);
            if (result.isSuccess()) {
                OssObjectInfoResultDto resultDto = (OssObjectInfoResultDto) result.getData();
                //                        TODO  先判断该附件是否存在，不存在则更新
                PlateAnnex plateAnnex = plateAnnexMapper.selectOne(new LambdaQueryWrapper<PlateAnnex>().eq(PlateAnnex::getPlateId, reqDto.getPlateId()).eq(PlateAnnex::getAnnexType, reqDto.getFileType()));
                if (plateAnnex == null) {
                    updateFlag = true;
                    plateAnnex = new PlateAnnex();
                    plateAnnex.setCreateId(reqDto.getUid());
                    plateAnnex.setCreateTime(LocalDateTime.now());
                    plateAnnex.setCreateBy(userInfo.getData().getNickname());
                    plateAnnex.setAnnexSort(reqDto.getDriverId());
                } else {
                    updateFlag = false;
                    plateAnnex.setUpdateId(reqDto.getUid());
                    plateAnnex.setUpdateTime(LocalDateTime.now());
                    plateAnnex.setUpdateBy(userInfo.getData().getNickname());
                    plateAnnex.setAnnexSort(reqDto.getDriverId());
                    plateAnnex.setAnnexPath("");
                }
                plateAnnex.setPlateId(reqDto.getPlateId());
                plateAnnex.setOssId(resultDto.getId());
                //清空对应zz系统对应文件名称 标题 路径
                plateAnnex.setAnnexTitle(fileCode);
                plateAnnex.setAnnexName(fileName);
                plateAnnex.setAnnexType(reqDto.getFileType());

                //上传zz系统
                String resultInfo = "";
                try {
                    CloseableHttpClient httpClient = HttpClients.createDefault();
                    // 上传运管的路径
                    log.info("上传运管的接口路径 {}", CharterApplyLicense.UPLOAD_FILE_INFO);
                    HttpPost httpPost = new HttpPost(CharterApplyLicense.UPLOAD_FILE_INFO);
                    // 创建表单
                    MultipartEntityBuilder builder = MultipartEntityBuilder.create()
                            .setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
                    builder.setCharset(Charset.forName("UTF-8"));
                    builder.addBinaryBody("multipartFile", pdfBytes, ContentType.MULTIPART_FORM_DATA, fileName);
                    // 处理其他参数
                    builder.addTextBody("id", reqDto.getFileType());

                    HttpEntity httpEntity = builder.build();
                    httpPost.setEntity(httpEntity);
                    HttpResponse httpResponse = httpClient.execute(httpPost);
                    HttpEntity responseEntity = httpResponse.getEntity();
                    if (responseEntity != null) {
                        // 将响应内容转换为字符串
                        resultInfo = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
                    }
                    log.info("上传到运管的结果 {}", result);
                } catch (Exception e) {
                    log.error("上传运管出错 {}", e.getMessage());
                    return Result.failed("文件处理失败");
                }
                ///上传运管系统
                Map<String, String> map = CharterApplyLicense.receiveCharterLicenseData(RtabTokenHelper.KEY, resultInfo);
                if ("200".endsWith(map.get("code"))) {
                    UpLoadReturnDto upLoadReturnDto = JsonHelper.deserialize(map.get("data"), UpLoadReturnDto.class);
                    if (updateFlag) {
                        plateAnnex.setAnnexPath(upLoadReturnDto.getUrl());
                        plateAnnexMapper.insert(plateAnnex);
                    } else {
                        plateAnnex.setAnnexPath(upLoadReturnDto.getUrl());
                        plateAnnexMapper.updateById(plateAnnex);
                    }
                    Map returnMap = new HashMap();
                    returnMap.put("url", resultDto.getUrl());
                    return Result.success(returnMap);
                } else {
                    return Result.failed(map.get("data"));
                }
            } else {
                return Result.failed("上传任何文件异常");
            }
        } else {
            return Result.failed("文件处理失败");
        }
    }

    @Override
    public Result<?> GetUploadInfoByPlateId(GetUpLoadInfoReqDto reqDto) {
        List<PlateAnnexDto> plateAnnexDtos = ConvertUtil.copyList(plateAnnexMapper.selectList(new LambdaQueryWrapper<PlateAnnex>().eq(PlateAnnex::getPlateId, reqDto.getPlateId())), PlateAnnexDto.class);
        GetUpLoadInfoResDto res = new GetUpLoadInfoResDto();
        res.setPlateId(reqDto.getPlateId());
        //处理附件访问地址
        plateAnnexDtos.stream().forEach(plateAnnexDto -> {
            plateAnnexDto.setOssPath(fileUploadService.getFile(plateAnnexDto.getOssId()));
        });
        res.setPlateAnnexs(plateAnnexDtos);
        //设置驾驶员信息
        res.setDrivers(ConvertUtil.copyList(plateDriverMapper.selectList(new LambdaQueryWrapper<PlateDriver>().eq(PlateDriver::getPlateId, reqDto.getPlateId())), DriverInfoDto.class));
        return Result.success(res);
    }

    /**
     * case "file0": fileName = "包车牌申请表.pdf";fileCode = "201";
     * case "file1":fileName = "包车合同.pdf";      fileCode = "202";
     * case "file2":      fileName = "行驶证.pdf";      fileCode = "203";
     * case "file3":      fileName = "驾驶证.pdf";fileCode = "204";
     * case "file4":      fileName = "驾驶证-副驾.pdf";fileCode = "205";
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<?> saveApply(GetUpLoadInfoReqDto reqDto) {
        //查询该包车牌iD下对应多少个驾驶员
        Long driverCount = plateDriverMapper.selectCount(new LambdaQueryWrapper<PlateDriver>().eq(PlateDriver::getPlateId, reqDto.getPlateId()));
        if (driverCount > 2 || driverCount == 0) {
            return Result.failed("驾驶员数量异常");
        }
        //获取附件列表信息
        List<PlateAnnex> plateAnnexes = plateAnnexMapper.selectList(new LambdaQueryWrapper<PlateAnnex>().eq(PlateAnnex::getPlateId, reqDto.getPlateId()));
        // 检查必需的文件类型是否都存在
        Set<String> requiredFileTypes = new HashSet<String>() {{
            add(UploadFileTypeEnum.CHARTER_PLATE_APPLICATION_FORM.getCode());
            add(UploadFileTypeEnum.CHARTER_CONTRACT.getCode());
            add(UploadFileTypeEnum.VEHICLE_LICENSE.getCode());
            add(UploadFileTypeEnum.DRIVING_LICENSE.getCode());
        }};

        if (driverCount == 2) {
            requiredFileTypes = new HashSet<String>() {{
                add(UploadFileTypeEnum.CHARTER_PLATE_APPLICATION_FORM.getCode());
                add(UploadFileTypeEnum.CHARTER_CONTRACT.getCode());
                add(UploadFileTypeEnum.VEHICLE_LICENSE.getCode());
                add(UploadFileTypeEnum.DRIVING_LICENSE.getCode());
                add(UploadFileTypeEnum.CO_DRIVER_LICENSE.getCode());
            }};
        }
        // 从plateAnnexes中筛选出符合条件的数据
        Set<String> finalRequiredFileTypes = requiredFileTypes;
        plateAnnexes = plateAnnexes.stream().filter(annex -> finalRequiredFileTypes.contains(annex.getAnnexTitle())).collect(Collectors.toList());
        if (plateAnnexes == null || plateAnnexes.isEmpty() || plateAnnexes.size() < (driverCount + 3)) {
            return Result.failed("请上传包车牌申请中所需的文件");
        }

        Result<UserResDto> userInfo = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!userInfo.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        // 定义文件类型与中文描述的映射关系
        Map<String, String> fileTypeDescriptions = new HashMap<>();
        fileTypeDescriptions.put(UploadFileTypeEnum.CHARTER_PLATE_APPLICATION_FORM.getCode(), UploadFileTypeEnum.CHARTER_PLATE_APPLICATION_FORM.getDescription());
        fileTypeDescriptions.put(UploadFileTypeEnum.CHARTER_CONTRACT.getCode(), UploadFileTypeEnum.CHARTER_CONTRACT.getDescription());
        fileTypeDescriptions.put(UploadFileTypeEnum.VEHICLE_LICENSE.getCode(), UploadFileTypeEnum.VEHICLE_LICENSE.getDescription());
        fileTypeDescriptions.put(UploadFileTypeEnum.DRIVING_LICENSE.getCode(), UploadFileTypeEnum.DRIVING_LICENSE.getDescription());
        fileTypeDescriptions.put(UploadFileTypeEnum.CO_DRIVER_LICENSE.getCode(), UploadFileTypeEnum.CO_DRIVER_LICENSE.getDescription());


        Set<String> existingFileTypes = plateAnnexes.stream().map(PlateAnnex::getAnnexTitle).filter(Objects::nonNull).collect(Collectors.toSet());
        // 找出缺失的文件类型
        List<String> missingFileTypes = requiredFileTypes.stream().filter(fileType -> !existingFileTypes.contains(fileType)).collect(Collectors.toList());

        if (!missingFileTypes.isEmpty()) {
            // 构建缺失文件的中文描述列表
            List<String> missingFileDescriptions = missingFileTypes.stream().map(fileType -> fileTypeDescriptions.getOrDefault(fileType, fileType)).collect(Collectors.toList());
            return Result.failed("缺少必要的附件文件: " + String.join(", ", missingFileDescriptions));
        }

        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        PlateOwner plateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        if (plate == null || StringHelper.isEmpty(plate.getTradeAppNumber()) || plateOwner == null || StringHelper.isEmpty(plateOwner.getLiceno())) {
            return Result.failed("缺少包车相关信息，请联系管理员");
        }
        //组装信息提交zz系统
        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setSaveApplyInfo(plate, plateOwner, plateAnnexes)), CharterApplyLicense.MTASAVE_DRAFT);
        if ("200".equals(map.get("code"))) {
            //操作日志记录保存
            super.addOperateLog(plate.getId(), reqDto.getUid(), OperateLogTempEnum.SUBMIT_APPLY, false);
            //更新
            plate.setCharterPlateStatus(CharterPlateStatusEnum.SIGN.getCode());
            plate.setUpdateTime(LocalDateTime.now());
            plate.setUpdateId(reqDto.getUid());
            plate.setUpdateBy(userInfo.getData().getNickname());
            plateMapper.updateById(plate);
            return Result.success(map.get("data"));
        } else {
            return Result.failed(map.get("data"));
        }
    }

    /**
     * 提交审核接口组装
     *
     * @param
     * @return
     */
    public Map<String, Object> setSaveApplyInfo(Plate plate, PlateOwner plateOwner, List<PlateAnnex> plateAnnexes) {
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("appno", plate.getTradeAppNumber());
        // 构造 attachments 数组
        JSONArray attachmentsArray = new JSONArray();
        for (PlateAnnex annex : plateAnnexes) {
            JSONObject attachment = new JSONObject();
            attachment.put("annextype", annex.getAnnexTitle()); // 文件类型编码，如201、202等
            attachment.put("storageaddress", annex.getAnnexPath()); // 文件存储路径
            attachment.put("annexname", annex.getAnnexName()); // 文件名称
            attachmentsArray.add(attachment);
        }
        jsonParam.put("attachments", attachmentsArray);
        jsonParam.put("applyPageType", "add");
        jsonParam.put("businesstype", "ffbc001");
        jsonParam.put("processType", "91180003");
        jsonParam.put("taskStatus", "91190001");
        jsonParam.put("operatorcode", plateOwner.getLiceno());
        return jsonParam;
    }

    /**
     * 终止包车牌
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<?> stopCharterPlate(StopCharterPlateReqDto reqDto) {
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        if (plate == null || StringHelper.isEmpty(plate.getTradeAppNumber())) {
            return Result.failed("包车牌不存在");
        }
        PlateOwner plateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        if (plateOwner == null || StringHelper.isEmpty(plateOwner.getLiceno())) {
            return Result.failed("包车业户信息不存在");
        }

        if (!StringHelper.isEmpty(reqDto.getCharterPlateStatus())) {
            if (Integer.parseInt(reqDto.getCharterPlateStatus()) != plate.getCharterPlateStatus()) {
                return Result.failed("当前状态不是" + CharterPlateStatusEnum.get(plate.getCharterPlateStatus()).getDescription());
            }
        }

        Result<UserResDto> userInfo = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!userInfo.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }

        Map<String, String> map;
        //已审核未打印终止
        if (plate.getCharterPlateStatus() == CharterPlateStatusEnum.REVIEWED.getCode()) {
            map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setStopCharterPlateInfo(plate, plateOwner)), CharterApplyLicense.TO_EXAMINERMINATION);
        } else if (plate.getCharterPlateStatus() == CharterPlateStatusEnum.REVIEWED.getCode()) {
            //  作废重打后终止
            map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setStopCharterPlateInfo(plate, plateOwner)), CharterApplyLicense.TO_VOIDMINATION);
        } else if (plate.getCharterPlateStatus() == CharterPlateStatusEnum.REVIEW.getCode()) {
            map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setStopCharterPlateInfo(plate, plateOwner)), CharterApplyLicense.TO_WAITCHECKMINATION);
        } else {
            map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setStopCharterPlateInfo(plate, plateOwner)), CharterApplyLicense.DIRECT_TO_WAITCHECKMINATION);
        }
        if ("200".equals(map.get("code"))) {
            //更新
            plate.setCharterPlateStatus(CharterPlateStatusEnum.TERMINATED.getCode());
            plate.setUpdateTime(LocalDateTime.now());
            plate.setUpdateId(reqDto.getUid());
            plate.setUpdateBy(userInfo.getData().getNickname());
            plateMapper.updateById(plate);
            //操作日志记录保存
            super.addOperateLog(plate.getId(), reqDto.getUid(), OperateLogTempEnum.TERMINATE_APPLY, false);
            return Result.success(map.get("data"));
        } else {
            return Result.failed(map.get("data"));
        }
    }

    public Map<String, Object> setStopCharterPlateInfo(Plate plate, PlateOwner plateOwner) {
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("appnumber", plate.getTradeAppNumber());
        jsonParam.put("operatorcode", plateOwner.getLiceno());
        return jsonParam;
    }

    @Override
    public Result<?> plateArchivedAndCancel(PlateArchivedAndCancelReqDto reqDto) {
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        if (plate == null) {
            return Result.failed("包车牌不存在");
        }
        if (CharterPlateStatusEnum.PRINTED.getCode() != plate.getCharterPlateStatus() || plate.getPlateProduceType() != CharterPlateProductTypeEnum.PAPER_CHARTER_PLATE.getCode()) {
            return Result.failed("不是纸质包车牌或者状态不是已打印");
        }
        PlateOwner plateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        if (plateOwner == null || StringHelper.isEmpty(plateOwner.getLiceno())) {
            return Result.failed("包车牌缺少必要信息，请联系管理员");
        }

        Result<UserResDto> userInfo = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!userInfo.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }

        Map<String, String> map;
        //作废重打
        if (CharterPlateStatusEnum.REPRINT.getCode().equals(reqDto.getPlateOperType())) {
            map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setPlateArchivedAndCancelInfo(plate, plateOwner)), CharterApplyLicense.GET_CANCEL);

            //  归档
        } else if (plate.getCharterPlateStatus() == CharterPlateStatusEnum.ARCHIVED.getCode()) {
            map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setPlateArchivedAndCancelInfo(plate, plateOwner)), CharterApplyLicense.UPDATE_BCP_ARCHIVEDLIST);
        } else {
            return Result.failed("包车牌当前操作类型只能是归档或作废重打");
        }

        if ("200".equals(map.get("code"))) {
            //操作日志记录保存
            if (CharterPlateStatusEnum.REPRINT.getCode().equals(reqDto.getPlateOperType())) {
                //更新状态为已更新未打印
                plate.setCharterPlateStatus(CharterPlateStatusEnum.REVIEWED.getCode());
            } else {
                //更新状态为已归档
                plate.setCharterPlateStatus(CharterPlateStatusEnum.ARCHIVED.getCode());
            }

            plate.setUpdateTime(LocalDateTime.now());
            plate.setUpdateId(reqDto.getUid());
            plate.setUpdateBy(userInfo.getData().getNickname());
            plateMapper.updateById(plate);
            //操作日志记录保存
            super.addOperateLog(plate.getId(), reqDto.getUid(), CharterPlateStatusEnum.REPRINT.getCode().equals(reqDto.getPlateOperType()) ? OperateLogTempEnum.INVALIDATE_APPLY : OperateLogTempEnum.ARCHIVE_APPLY, false);
            return Result.success(map.get("data"));
        } else {
            return Result.failed(map.get("data"));
        }
    }

    @Override
    public Result<?> plateArchivedAndCancel2(PlateArchivedAndCancelReqDto2 reqDto) {
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        if (plate == null) {
            return Result.failed("包车牌不存在");
        }
        if (CharterPlateStatusEnum.GENERATED.getCode() != plate.getCharterPlateStatus() || plate.getPlateProduceType() != CharterPlateProductTypeEnum.ELECTRONIC_CHARTER_PLATE.getCode()) {
            return Result.failed("不是电子包车牌或者状态不是已生成包车牌");
        }
        PlateOwner plateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        if (plateOwner == null || StringHelper.isEmpty(plateOwner.getLiceno())) {
            return Result.failed("包车牌缺少必要信息，请联系管理员");
        }

        Result<UserResDto> userInfo = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!userInfo.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }

        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setPlateArchivedAndCancelInfo(plate, plateOwner)), CharterApplyLicense.UPDATE_BCP_ARCHIVEDLIST);

        if ("200".equals(map.get("code"))) {
            plate.setUpdateTime(LocalDateTime.now());
            plate.setUpdateId(reqDto.getUid());
            plate.setUpdateBy(userInfo.getData().getNickname());
            plateMapper.updateById(plate);
            // 操作日志记录保存
            super.addOperateLog(plate.getId(), reqDto.getUid(), OperateLogTempEnum.ARCHIVE_APPLY, false);
            return Result.success(map.get("data"));
        } else {
            return Result.failed(map.get("data"));
        }
    }

    @Override
    public Result<?> taskUpdateState(PlateUpdateStatueReqDto reqDto) {
        List<Plate> plates = plateMapper.selectList(new LambdaQueryWrapper<Plate>().in(Plate::getId, reqDto.getPlateIds()));
        List<Long> updatePlateIds = new ArrayList<>();
        if (plates != null && !plates.isEmpty()) {
            Result<UserResDto> userInfo = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
            if (!userInfo.isSuccess()) {
                return Result.failed("获取用户信息异常");
            }
            plates.forEach(plate -> {
                //TODO 2025/10/23 还需要排除本地是已打印状态的 已打印不需更同步 以免影响补录功能
                if (!StringHelper.isEmpty(plate.getTradeAppNumber()) && plate.getCharterPlateStatus() != CharterPlateStatusEnum.PRINTED.getCode()) {
                    JSONObject jsonParam = new JSONObject();
                    jsonParam.put("appnumber", plate.getTradeAppNumber());
                    Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(jsonParam), CharterApplyLicense.MTA_SYS_STATUS);
                    if ("200".equals(map.get("code"))) {
                        LicenseInfoDto returnData = JsonHelper.deserialize(map.get("data"), LicenseInfoDto.class);
                        if (plate.getTradeAppNumber().equals(returnData.getAppNumber()) && !StringHelper.isEmpty(returnData.getState())) {
                            plate.setTradeCharterPlateStatus(Integer.parseInt(returnData.getState()));
                            CharterPlateStatusEnum statusEnum = CharteredLicenseConstant.PLATE_TRADE_STATUS.get(Integer.parseInt(returnData.getState()));
                            if (statusEnum != null) {
                                plate.setCharterPlateStatus(statusEnum.getCode());
                            }
                            plate.setUpdateId(reqDto.getUid());
                            plate.setUpdateTime(LocalDateTime.now());
                            plate.setUpdateBy(userInfo.getData().getNickname());
                            plateMapper.updateById(plate);
                            updatePlateIds.add(plate.getId());
                        }
                    }
                }
            });
        }
        return Result.success(updatePlateIds);
    }

    /**
     * 打印补录
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<?> printSupplement(PlateUpdateStatueReqDto reqDto) {
        List<Plate> plates = plateMapper.selectList(new LambdaQueryWrapper<Plate>().in(Plate::getId, reqDto.getPlateIds()));
        List<Long> updatePlateIds = new ArrayList<>();
        plates.forEach(plate -> {
            ReprintTask reprintTask = reprintTaskService.getBaseMapper().selectById(plate.getId());
            if (reprintTask == null) {
                PlateOwner plateOwner = plateOwnerMapper.selectById(plate.getId());
                PlateLine plateLine = plateLineMapper.selectById(plate.getId());
                if (plate != null && !StringHelper.isEmpty(plate.getTradeAppNumber()) && plateOwner != null && !StringHelper.isEmpty(plateOwner.getLiceno()) && plateLine != null) {
                    //还需要判断是否符合补录
                    if (plate.getTradeCharterPlateStatus() == CharteredLicenseConstant.TRADE_PLATE_STATUS.get(CharterPlateStatusEnum.GENERATED) && plate.getCharterPlateStatus() == CharterPlateStatusEnum.PRINTED.getCode() && plate.getPlateProduceType() == CharterPlateProductTypeEnum.PAPER_CHARTER_PLATE.getCode()) {
                        Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setProcessReprintRetryInfo(plate, plateOwner, plateLine)), CharterApplyLicense.FEEDBACK_PRINT_INFORMATION);
                        if ("200".equals(map.get("code"))) {
                            //系统补录成功
                            plate.setPrintSupplementStatus(RePrintStatusEnum.MANUAL_REPRINT_SUCCESS.getCode());
                            plate.setTradeCharterPlateStatus(CharteredLicenseConstant.TRADE_PLATE_STATUS.get(CharterPlateStatusEnum.PRINTED));
                            //操作日志记录保存
                            super.addOperateLog(plate.getId(), reqDto.getUid(), OperateLogTempEnum.REPRINT_SUCCESS_APPLY, false);
                            plateMapper.updateById(plate);
                            updatePlateIds.add(plate.getId());
                        } else {
                            //系统补录成功
                            plate.setPrintSupplementStatus(RePrintStatusEnum.MANUAL_REPRINT_FAILED.getCode());
                            //操作日志记录保存
                            super.addOperateLog(plate.getId(), reqDto.getUid(), OperateLogTempEnum.REPRINT_FAIL_APPLY, false);
                            plateMapper.updateById(plate);
                        }
                    }
                }
            }
        });
        return Result.success(updatePlateIds);
    }

    /**
     * s数据补录任务处理
     */
    @Override
    public void processReprintRetry() {
        long tenMinutesAgo = System.currentTimeMillis() - 10 * 60 * 1000;
        List<ReprintTask> reprintTasks = reprintTaskService.getBaseMapper().selectList(new LambdaQueryWrapper<ReprintTask>().ne(ReprintTask::getStatus, 2).lt(ReprintTask::getLastRetryTime, tenMinutesAgo).lt(ReprintTask::getRetryCount, 3));
        if (reprintTasks != null && !reprintTasks.isEmpty()) {
            reprintTasks.forEach(task -> {
                Long plateId = task.getId();
                RLock lock = null;
                try {
                    lock = redissonClient.getLock(OrderLockUtils.getLockKey(plateId));
                    if (!lock.tryLock(OrderLockUtils.LOCK_WAIT_TIME_SECOND, TimeUnit.SECONDS)) {
                        doTaskHandle(task);
                    }
                } catch (Exception e) {
                    log.error("数据补录异常：{}", plateId, e);
                    if (e instanceof BusinessException) {
                        throw (BusinessException) e;
                    }
                } finally {
                    if (Objects.nonNull(lock) && lock.isLocked()) {
                        lock.unlock();
                    }
                }
            });
        }
    }


    //1：申请数据  2：包车牌   不传就是全部
    private void doExportLogRecord(UserResDto userInfo, String fileName, String exportType, Long uid) {
        ExportRecord exportRecord = new ExportRecord();
        exportRecord.setCreateId(uid);
        exportRecord.setCreateBy(userInfo.getNickname());
        exportRecord.setCreateTime(LocalDateTime.now());
        if ("1".equals(exportType)) {
            exportRecord.setTitle("导出申请数据");
            exportRecord.setContent("导出申请数据，数据范围：" + fileName);
        } else if ("2".equals(exportType)) {
            exportRecord.setTitle("导出包车牌");
            exportRecord.setContent("导出包车牌，数据范围：" + fileName);
        } else {
            exportRecord.setTitle("导出申请数据和包车牌");
            exportRecord.setContent("导申请数据和包车牌，数据范围：" + fileName);
        }
        exportRecordService.getBaseMapper().insert(exportRecord);
    }

    /**
     * 申请数据导出
     *
     * @param exportReqDto
     * @return
     */
    @Override
    public Result<?> plateInfoExport(PlateDraftPageReqDto exportReqDto) {
        // 获取用户信息
        UserResDto userInfo = UserSessionManager.getMerchantUser(exportReqDto.getUid());
        if (userInfo == null || StringHelper.isEmpty(userInfo.getOrgVo())) {
            return Result.failed("获取用户信息异常");
        }
        FileNameAndNumDto fileNameAndNumDto = generateZipFileName(exportReqDto);
        if (StringHelper.isEmpty(fileNameAndNumDto.getFileName()) || fileNameAndNumDto.getNum() > 5000) {
            return Result.failed("当前查询条件下没有数据或数据量大于5000条,请分批次导出。");
        }
        Map returnMap = new HashMap();
        if ("1".equals(exportReqDto.getExportType())) {
            //数据execl文件
            returnMap.put("url", plateExportService.exportWithFileName(exportReqDto).getUrl());
            doExportLogRecord(userInfo, fileNameAndNumDto.getFileName(), exportReqDto.getExportType(), exportReqDto.getUid());
            return Result.success(returnMap);
        } else if ("2".equals(exportReqDto.getExportType())) {
            String zipFileName = "包车牌" + fileNameAndNumDto.getFileName().replaceAll(" \\d{6}", "") + ".zip";
            List<ExportDto> allFiles = new ArrayList<>();
            allFiles.addAll(generatePdfFilesForExport(exportReqDto));
            // 将多个文件打包成压缩包
            byte[] zipBytes = packageFilesToZip(allFiles);
            // 将压缩包上传到OSS并返回下载链接
            MultipartFile multipartFile = new ByteArrayMultipartFile(zipBytes, zipFileName, "application/zip");
            Result<?> result = fileUploadService.uploadOss(multipartFile);
            if (result.isSuccess()) {
                OssObjectInfoResultDto data = (OssObjectInfoResultDto) result.getData();
                doExportLogRecord(userInfo, fileNameAndNumDto.getFileName(), exportReqDto.getExportType(), exportReqDto.getUid());
                returnMap.put("url", data.getUrl());
                return Result.success(returnMap);
            } else {
                return Result.failed("导出文件失败");
            }
        } else {
            // 从exportReqDto中获取文件URL列表
            //数据execl文件
            ExportDto exportDto = plateExportService.exportWithFileName(exportReqDto);
            if (exportDto == null || StringHelper.isEmpty(exportDto.getUrl())) {
                return Result.failed("没有找到可导出的文件");
            }
            // 生成压缩包名称：包车牌+时间区间
            String zipFileName = "申请数据-包车牌" + fileNameAndNumDto.getFileName().replaceAll(" \\d{6}", "") + ".zip";
            List<ExportDto> allFiles = new ArrayList<>();
            allFiles.add(exportDto);
            allFiles.addAll(generatePdfFilesForExport(exportReqDto));
            // 将多个文件打包成压缩包
            byte[] zipBytes = packageFilesToZip(allFiles);
            // 将压缩包上传到OSS并返回下载链接
            MultipartFile multipartFile = new ByteArrayMultipartFile(zipBytes, zipFileName, "application/zip");
            Result<?> result = fileUploadService.uploadOss(multipartFile);
            if (result.isSuccess()) {
                OssObjectInfoResultDto data = (OssObjectInfoResultDto) result.getData();
                returnMap.put("url", data.getUrl());
                doExportLogRecord(userInfo, fileNameAndNumDto.getFileName(), exportReqDto.getExportType(), exportReqDto.getUid());
                return Result.success(returnMap);
            } else {
                return Result.failed("导出文件失败");
            }
        }
    }

    @Override
    public Result<?> exportRecord(ExportRecordReqDto reqDto) {
        startPage(reqDto.getPageNum(), reqDto.getPageSize());
        List<ExportRecord> records = exportRecordService.getBaseMapper().selectList(new LambdaQueryWrapper<ExportRecord>().eq(ExportRecord::getCreateId, reqDto.getUid()));
        PageInfo<ExportRecord> pageInfo = new PageInfo<>(records);
        return Result.success(pageInfo.getList(), pageInfo.getTotal());
    }

    /**
     * 打印包车牌
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<?> printPlate(PlatePrintReqDto reqDto) {
        Result<UserResDto> userInfo = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!userInfo.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        if (plate == null || !CharterPlateStatusEnum.GENERATED.getCode().equals(plate.getCharterPlateStatus())) {
            return Result.failed("包车牌不存在或者当前状态不是已生成包车牌");
        }

        PlateOwner plateOwner = plateOwnerMapper.selectById(reqDto.getPlateId());
        if (plateOwner == null) {
            return Result.failed("包车牌所有者不存在");
        }
        PlateLine plateLine = plateLineMapper.selectById(reqDto.getPlateId());
        if (plateLine == null) {
            return Result.failed("包车牌运管运次不存在");
        }
        //TODO 2025/10/27 如果是纸质包车牌需要发送答应通知到zz系统 如果是电子包车牌直接记录日志
        if (plate.getPlateProduceType().equals(CharterPlateProductTypeEnum.PAPER_CHARTER_PLATE.getCode())) { // 电子包车牌
            Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setProcessReprintRetryInfo(plate, plateOwner, plateLine)), CharterApplyLicense.FEEDBACK_PRINT_INFORMATION);
            if ("200".equals(map.get("code"))) {
                //系统补录成功
                plate.setTradeCharterPlateStatus(CharteredLicenseConstant.TRADE_PLATE_STATUS.get(CharterPlateStatusEnum.PRINTED));
                plate.setUpdateBy(userInfo.getData().getNickname());
                plate.setUpdateId(reqDto.getUid());
                plate.setUpdateTime(LocalDateTime.now());
                plateMapper.updateById(plate);
            }
        }
        //操作日志记录保存
        super.addOperateLog(plate.getId(), reqDto.getUid(), OperateLogTempEnum.PRINT_LICENSE, false);
        return Result.success("打印记录推送成功");
    }

    /**
     * 下载包车牌
     *
     * @param reqDto
     * @return
     */
    @Override
    public Result<?> downloadPlate(PlatePrintReqDto reqDto) {
        Result<UserResDto> userInfo = merchantFeignClient.getUserByUserId(UserReqDto.builder().uid(reqDto.getUid()).build());
        if (!userInfo.isSuccess()) {
            return Result.failed("获取用户信息异常");
        }
        Plate plate = plateMapper.selectById(reqDto.getPlateId());
        if (plate == null || StringHelper.isEmpty(plate.getLocalFilePath())) {
            return Result.failed("包车牌不存在或者当前还未生成包车牌");
        }
        String file = fileUploadService.getFile(Long.valueOf(plate.getLocalFilePath()));
        if (StringHelper.isEmpty(file)) {
            return Result.failed("下载文件失败");
        }
        //操作日志记录保存
        super.addOperateLog(plate.getId(), reqDto.getUid(), OperateLogTempEnum.DOWNLOAD_LICENSE, false);
        Map<String, String> returnMap = new HashMap<>();
        returnMap.put("url", file);
        return Result.success(returnMap);
    }

    @Transactional(rollbackFor = Exception.class)
    public void doTaskHandle(ReprintTask task) {
        Long plateId = task.getId();
        Plate plate = plateMapper.selectById(plateId);
        PlateOwner plateOwner = plateOwnerMapper.selectById(plateId);
        PlateLine plateLine = plateLineMapper.selectById(plateId);
        if (plate != null && !StringHelper.isEmpty(plate.getTradeAppNumber()) && plateOwner != null && !StringHelper.isEmpty(plateOwner.getLiceno()) && plateLine != null) {
            Map<String, String> map = CharterApplyLicense.gainCharterLicenseData(JSON.toJSONString(setProcessReprintRetryInfo(plate, plateOwner, plateLine)), CharterApplyLicense.FEEDBACK_PRINT_INFORMATION);
            if ("200".equals(map.get("code"))) {
                task.setStatus(2);
                //操作日志记录保存
                plate.setTradeCharterPlateStatus(CharteredLicenseConstant.TRADE_PLATE_STATUS.get(CharterPlateStatusEnum.PRINTED));
                super.addOperateLog(plate.getId(), null, OperateLogTempEnum.REPRINT_SUCCESS_APPLY, true);
                //系统补录成功
                plate.setPrintSupplementStatus(RePrintStatusEnum.SYSTEM_REPRINT_SUCCESS.getCode());
                plateMapper.updateById(plate);
            } else {
                task.setRetryCount(task.getRetryCount() + 1);
                task.setStatus(1);
                task.setLastRetryTime(System.currentTimeMillis());
                //系统补录失败
                if (task.getRetryCount() > 2) {
                    //系统补录成
                    plate.setPrintSupplementStatus(RePrintStatusEnum.SYSTEM_REPRINT_FAILED.getCode());
                    //操作日志记录保存
                    super.addOperateLog(plate.getId(), null, OperateLogTempEnum.REPRINT_FAIL_APPLY, true);
                    plateMapper.updateById(plate);
                }
            }
            reprintTaskService.updateById(task);
        }
    }

    public Map<String, Object> setProcessReprintRetryInfo(Plate plate, PlateOwner plateOwner, PlateLine plateLine) {
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("appnumber", plate.getTradeAppNumber());
        jsonParam.put("PrintLicPlaID", plate.getPrintLicPlaId() == null ? "" : plate.getPrintLicPlaId());
        jsonParam.put("statue", "4002");
        jsonParam.put("operatorcode", plateOwner.getLiceno());
        jsonParam.put("cardtype", plateLine.getCardType() == null ? "" : plateLine.getCardType());
        //2 补录 1 打印或作废重打
        jsonParam.put("cancel", "2");
        return jsonParam;
    }


    /**
     * 设置作废重打信息
     *
     * @param plate
     * @param plateOwner
     * @return
     */
    public Map<String, Object> setPlateArchivedAndCancelInfo(Plate plate, PlateOwner plateOwner) {
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("printlicplaid", plate.getPrintLicPlaId() == null ? "" : plate.getPrintLicPlaId());
        jsonParam.put("operatorcode", plateOwner.getLiceno());
        return jsonParam;
    }

    /**
     * 保存PDF文件到本地临时目录
     */
    private String savePdfFile(MultipartFile file, String type) throws IOException {
        String savePath = generateSavePath(type, "pdf");
        File destFile = new File(savePath);
        FileUtils.forceMkdirParent(destFile);
        file.transferTo(destFile);
        return savePath;
    }

    /**
     * 生成文件保存路径
     */
    private String generateSavePath(String type, String extension) {
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return "/tmp/upload/" + type + "/" + uuid + "." + extension;
    }

    /**
     * 将多张图片合并为PDF
     */
    private byte[] convertMultipleImagesToPdf(MultipartFile[] imageFiles, String type) throws Exception {
        // 生成PDF保存路径
        String pdfSavePath = generateSavePath(type, "pdf");
        // 这里需要实现多张图片转PDF的逻辑
        // 可以使用Apache PDFBox或其他库来实现
        return convertMultipleImageFilesToPdf(imageFiles, pdfSavePath);
    }

    /**
     * 多张图片转PDF实现
     */
    private byte[] convertMultipleImageFilesToPdf(MultipartFile[] imageFiles, String pdfSavePath) throws Exception {
        PDDocument document = new PDDocument();
        try {
            // 依次处理每张图片并添加到PDF
            for (MultipartFile imageFile : imageFiles) {
                // 读取图片字节数组
                byte[] imageBytes = imageFile.getBytes();
                // 根据文件扩展名判断图片类型并创建PDImageXObject
                String filename = imageFile.getOriginalFilename().toLowerCase();
                PDImageXObject pdImage;
                if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {
                    pdImage = PDImageXObject.createFromByteArray(document, imageBytes, "jpeg");
                } else if (filename.endsWith(".png")) {
                    pdImage = PDImageXObject.createFromByteArray(document, imageBytes, "png");
                } else if (filename.endsWith(".bmp")) {
                    pdImage = PDImageXObject.createFromByteArray(document, imageBytes, "bmp");
                } else {
                    // 默认处理
                    pdImage = PDImageXObject.createFromByteArray(document, imageBytes, filename);
                }
                // 使用A4标准页面尺寸
                PDPage page = new PDPage(PDRectangle.A4);
                document.addPage(page);
                // 获取页面和图片尺寸
                float pageWidth = page.getMediaBox().getWidth();
                float pageHeight = page.getMediaBox().getHeight();
                float imageWidth = pdImage.getWidth();
                float imageHeight = pdImage.getHeight();

                // 如果图片尺寸小于页面尺寸，使用原始大小；否则按比例缩放
                float finalWidth, finalHeight;
                if (imageWidth <= pageWidth && imageHeight <= pageHeight) {
                    // 图片比页面小，使用原始大小
                    finalWidth = imageWidth;
                    finalHeight = imageHeight;
                } else {
                    // 图片比页面大，按比例缩放
                    float scale = Math.min(pageWidth / imageWidth, pageHeight / imageHeight);
                    finalWidth = imageWidth * scale;
                    finalHeight = imageHeight * scale;
                }
                // 计算居中位置
                float x = (pageWidth - finalWidth) / 2;
                float y = (pageHeight - finalHeight) / 2;
                // 创建绘图内容流
                try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
                    // 绘制图片到页面
                    contentStream.drawImage(pdImage, x, y, finalWidth, finalHeight);
                }
            }
            // 保存PDF文件
//            File pdfFile = new File(pdfSavePath);
//            FileUtils.forceMkdirParent(pdfFile);
//            document.save(pdfFile);
            // 将PDF文档转换为字节数组
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            document.save(baos);
            return baos.toByteArray();
        } finally {
            document.close();
        }
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || filename.lastIndexOf(".") == -1) {
            return "";
        }
        return filename.substring(filename.lastIndexOf(".") + 1);
    }

    /**
     * 将多个文件打包成压缩包
     *
     * @param fileUrls 文件的URL列表
     * @return 压缩包的字节数组
     */
    public byte[] packageFilesToZip(List<ExportDto> fileUrls) {
        if (fileUrls == null || fileUrls.isEmpty()) {
            throw new BusinessException("文件URL列表不能为空");
        }
        try {
            // 创建字节数组输出流，用于存储压缩包内容
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // 创建ZIP输出流
            ZipOutputStream zos = new ZipOutputStream(baos);
            // 设置压缩级别
            zos.setLevel(Deflater.DEFAULT_COMPRESSION);
            // 下载并添加每个文件到压缩包
            for (ExportDto fileUrl : fileUrls) {
                if (StringUtils.isBlank(fileUrl.getUrl()) || StringUtils.isBlank(fileUrl.getFileName())) {
                    continue;
                }
                try {
                    // 下载文件字节数组
                    byte[] fileBytes = HttpUtil.downloadBytes(fileUrl.getUrl());
                    if (fileBytes == null || fileBytes.length == 0) {
                        log.warn("文件下载失败或为空: {}", fileUrl.getUrl());
                        continue;
                    }
                    // 创建ZIP条目
                    ZipEntry zipEntry = new ZipEntry(fileUrl.getFileName());
                    zos.putNextEntry(zipEntry);
                    // 写入文件内容
                    zos.write(fileBytes);
                    // 完成当前条目
                    zos.closeEntry();
                    log.info("已添加文件到压缩包: {}", fileUrl.getFileName());
                } catch (Exception e) {
                    log.error("处理文件时出错: {}", fileUrl, e);
                    // 继续处理其他文件，不中断整个流程
                }
            }
            // 完成ZIP文件的创建
            zos.finish();
            zos.close();
            // 返回压缩包的字节数组
            return baos.toByteArray();
        } catch (Exception e) {
            log.error("打包文件为压缩包时出错", e);
            throw new BusinessException("打包文件为压缩包失败: " + e.getMessage());
        }
    }

    /**
     * 从URL中提取文件名
     */
    private String extractFileNameFromUrl(String url) {
        if (StringUtils.isBlank(url)) {
            return null;
        }

        try {
            // 解析URL
            URL urlObj = new URL(url);
            String path = urlObj.getPath();

            // 获取路径中的最后一部分作为文件名
            if (path != null && !path.isEmpty() && !path.endsWith("/")) {
                int lastSlashIndex = path.lastIndexOf('/');
                if (lastSlashIndex >= 0 && lastSlashIndex < path.length() - 1) {
                    return path.substring(lastSlashIndex + 1);
                }
            }

            // 如果无法从路径中提取文件名，尝试从查询参数中获取
            String query = urlObj.getQuery();
            if (query != null && !query.isEmpty()) {
                String[] params = query.split("&");
                for (String param : params) {
                    String[] keyValue = param.split("=");
                    if (keyValue.length == 2 && ("filename".equals(keyValue[0]) || "file".equals(keyValue[0]) || "name".equals(keyValue[0]))) {
                        return keyValue[1];
                    }
                }
            }

            return null;
        } catch (Exception e) {
            log.error("从URL提取文件名失败: {}", url, e);
            return null;
        }
    }

    /**
     * 判断是否为图片文件
     */
    private boolean isImageFile(String extension) {
        return "jpg".equals(extension) || "jpeg".equals(extension) ||
                "png".equals(extension) || "bmp".equals(extension) ||
                "gif".equals(extension);
    }

    /**
     * 为状态为4、5、6的包车牌生成PDF文件
     *
     * @param exportReqDto 导出请求参数
     * @return PDF文件列表
     */
    private List<ExportDto> generatePdfFilesForExport(PlateDraftPageReqDto exportReqDto) {
        resetReqDto(exportReqDto);
        List<ExportDto> pdfFiles = new ArrayList<>();
        // 获取用户信息
        UserResDto user = UserSessionManager.getMerchantUser(exportReqDto.getUid());
        if (user == null) {
            log.error("获取用户信息失败: {}", exportReqDto.getUid());
            return pdfFiles;
        }
        // 查询状态为4、5、6的包车牌数据
        List<PlateDraftPageResultDto> plateData = plateMapper.selectPlateDraftPage(exportReqDto);
        if (plateData == null || plateData.isEmpty()) {
            return pdfFiles;
        }
        // 过滤出状态为4、5、6的包车牌
        List<PlateDraftPageResultDto> filteredPlates = plateData.stream()
                .filter(plate -> plate.getCharterPlateStatus() != null && !StringHelper.isEmpty(plate.getLocalFilePath())).collect(Collectors.toList());
        // 为每个包车牌生成PDF文件
        for (PlateDraftPageResultDto plate : filteredPlates) {
            // 生成PDF文件名：包车牌号码-车牌号（有效期起-止）
            String pdfFileName = generatePdfFileName(plate);
            // 创建ExportDto对象
            ExportDto pdfFile = new ExportDto();
            pdfFile.setFileName(pdfFileName);
            pdfFile.setUrl(fileUploadService.getFile(Long.valueOf(plate.getLocalFilePath())));
            pdfFiles.add(pdfFile);
        }
        return pdfFiles;
    }

    /**
     * 生成PDF文件名：包车牌号码-车牌号（有效期起-止）
     *
     * @param plate 包车牌数据
     * @return PDF文件名
     */
    private String generatePdfFileName(PlateDraftPageResultDto plate) {
        StringBuilder fileName = new StringBuilder();
        // 包车牌号码
        if (plate.getCharterPlateNumber() != null && !plate.getCharterPlateNumber().isEmpty()) {
            fileName.append(plate.getCharterPlateNumber());
        } else {
            fileName.append("未知包车牌号");
        }
        fileName.append("-");
        // 车牌号
        if (plate.getPlateNumber() != null && !plate.getPlateNumber().isEmpty()) {
            fileName.append(plate.getPlateNumber());
        } else {
            fileName.append("未知车牌号");
        }
        fileName.append("（");
        // 有效期起
        if (plate.getBeginDate() != null) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            fileName.append(plate.getBeginDate().format(formatter));
        } else {
            fileName.append("未知开始日期");
        }
        fileName.append("-");
        // 有效期止
        if (plate.getEndDate() != null) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            fileName.append(plate.getEndDate().format(formatter));
        } else {
            fileName.append("未知结束日期");
        }
        fileName.append("）.pdf");
        return fileName.toString();
    }

    /**
     * 生成压缩包名称：包车牌+时间区间
     *
     * @param exportReqDto 导出请求参数
     * @return 压缩包文件名
     */
    private FileNameAndNumDto generateZipFileName(PlateDraftPageReqDto exportReqDto) {
        FileNameAndNumDto fileNameAndNumDto = new FileNameAndNumDto();
        resetReqDto(exportReqDto);
        // 查询包车牌数据
        List<PlateDraftPageResultDto> plateData = plateMapper.selectPlateDraftPage(exportReqDto);
        if (plateData == null || plateData.isEmpty()) {
            return fileNameAndNumDto;
        }
        fileNameAndNumDto.setNum(plateData.size());
        // 找出最早和最晚的创建时间
        LocalDateTime minTime = null;
        LocalDateTime maxTime = null;
        for (PlateDraftPageResultDto plate : plateData) {
            if (plate.getCreateTime() != null) {
                if (minTime == null || plate.getCreateTime().isBefore(minTime)) {
                    minTime = plate.getCreateTime();
                }
                if (maxTime == null || plate.getCreateTime().isAfter(maxTime)) {
                    maxTime = plate.getCreateTime();
                }
            }
        }
        // 格式化时间并生成文件名
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HHmmss");
        String fileName = "";
        if (minTime != null && maxTime != null) {
            fileName += minTime.format(formatter) + "-" + maxTime.format(formatter);
        }
        fileNameAndNumDto.setFileName(fileName);
        return fileNameAndNumDto;
    }

    /**
     * 重置列表查询参数
     *
     * @param reqDto
     */
    private void resetReqDto(PlateDraftPageReqDto reqDto) {
        UserResDto userReqDto = UserSessionManager.getMerchantUser(reqDto.getUid());
        if (CollectionUtils.isNotEmpty(reqDto.getOrgOrDptList())) {
            List<PlateDraftPageReqDto.OrgOrDptVo> orgOrDptList = reqDto.getOrgOrDptList();
            List<Long> orgIdList = orgOrDptList.stream().filter(o -> o.getOrgOrDptType().equals(1)).map(PlateDraftPageReqDto.OrgOrDptVo::getOrgId).collect(Collectors.toList());
            if (userReqDto.getDeptId() != null) {
                // 该用户绑定了部门，只能查询该部门数据
                orgIdList.remove(userReqDto.getOrgId());
            }
            List<Long> deptIdList = orgOrDptList.stream().filter(o -> o.getOrgOrDptType().equals(2)).map(PlateDraftPageReqDto.OrgOrDptVo::getOrgId).collect(Collectors.toList());
            reqDto.setOrgIdList(orgIdList);
            reqDto.setDeptIdList(deptIdList);
        } else {
            List<Long> orgIdList = sysDictService.userOrgIdList(reqDto.getUid());
            if (userReqDto.getDeptId() != null) {
                // 该用户绑定了部门，只能查询该部门数据
                orgIdList.remove(userReqDto.getOrgId());
            }
            reqDto.setOrgIdList(orgIdList);
            reqDto.setDeptIdList(sysDictService.userDeptIdList(reqDto.getUid()));
        }
        if (CollectionUtils.isEmpty(reqDto.getOrgIdList()) && CollectionUtils.isEmpty(reqDto.getDeptIdList())) {
            log.error("用户未绑定机构或部门，无法查询数据：{}", reqDto);
            throw new BusinessException(RetEnum.PARAM_ERROR);
        }
    }
}